]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dnsmasq/018-Move_code_which_caches_DS_records_to_a_more_logical_place.patch
kernel: update to 3.14.62
[ipfire-2.x.git] / src / patches / dnsmasq / 018-Move_code_which_caches_DS_records_to_a_more_logical_place.patch
CommitLineData
fbcc3cb7
MF
1From d64c81fff7faf4392b688223ef3a617c5c07e7dc Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Tue, 15 Dec 2015 16:11:06 +0000
4Subject: [PATCH] Move code which caches DS records to a more logical place.
5
6---
7 src/dnssec.c | 179 +++++++++++++++++++++++++++++-----------------------------
8 1 file changed, 90 insertions(+), 89 deletions(-)
9
10diff --git a/src/dnssec.c b/src/dnssec.c
11index 1ae03a6..359231f 100644
12--- a/src/dnssec.c
13+++ b/src/dnssec.c
14@@ -1204,7 +1204,10 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
15 int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
16 {
17 unsigned char *p = (unsigned char *)(header+1);
18- int qtype, qclass, val, i, neganswer, nons;
19+ int qtype, qclass, rc, i, neganswer, nons;
20+ int aclass, atype, rdlen;
21+ unsigned long ttl;
22+ struct all_addr a;
23
24 if (ntohs(header->qdcount) != 1 ||
25 !(p = skip_name(p, header, plen, 4)))
26@@ -1214,40 +1217,100 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
27 GETSHORT(qclass, p);
28
29 if (qtype != T_DS || qclass != class)
30- val = STAT_BOGUS;
31+ rc = STAT_BOGUS;
32 else
33- val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
34+ rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
35 /* Note dnssec_validate_reply() will have cached positive answers */
36
37- if (val == STAT_INSECURE)
38- val = STAT_BOGUS;
39-
40+ if (rc == STAT_INSECURE)
41+ rc = STAT_BOGUS;
42+
43 p = (unsigned char *)(header+1);
44 extract_name(header, plen, &p, name, 1, 4);
45 p += 4; /* qtype, qclass */
46
47- if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
48- val = STAT_BOGUS;
49-
50 /* If the key needed to validate the DS is on the same domain as the DS, we'll
51 loop getting nowhere. Stop that now. This can happen of the DS answer comes
52 from the DS's zone, and not the parent zone. */
53- if (val == STAT_BOGUS || (val == STAT_NEED_KEY && hostname_isequal(name, keyname)))
54+ if (rc == STAT_BOGUS || (rc == STAT_NEED_KEY && hostname_isequal(name, keyname)))
55 {
56 log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS");
57 return STAT_BOGUS;
58 }
59
60- if (val != STAT_SECURE)
61- return val;
62-
63- /* By here, the answer is proved secure, and a positive answer has been cached. */
64- if (neganswer)
65+ if (rc != STAT_SECURE)
66+ return rc;
67+
68+ if (!neganswer)
69 {
70- int rdlen, flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
71- unsigned long ttl, minttl = ULONG_MAX;
72- struct all_addr a;
73+ cache_start_insert();
74+
75+ for (i = 0; i < ntohs(header->ancount); i++)
76+ {
77+ if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
78+ return STAT_BOGUS; /* bad packet */
79+
80+ GETSHORT(atype, p);
81+ GETSHORT(aclass, p);
82+ GETLONG(ttl, p);
83+ GETSHORT(rdlen, p);
84+
85+ if (!CHECK_LEN(header, p, plen, rdlen))
86+ return STAT_BOGUS; /* bad packet */
87+
88+ if (aclass == class && atype == T_DS && rc == 1)
89+ {
90+ int algo, digest, keytag;
91+ unsigned char *psave = p;
92+ struct blockdata *key;
93+ struct crec *crecp;
94
95+ if (rdlen < 4)
96+ return STAT_BOGUS; /* bad packet */
97+
98+ GETSHORT(keytag, p);
99+ algo = *p++;
100+ digest = *p++;
101+
102+ /* Cache needs to known class for DNSSEC stuff */
103+ a.addr.dnssec.class = class;
104+
105+ if ((key = blockdata_alloc((char*)p, rdlen - 4)))
106+ {
107+ if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
108+ {
109+ blockdata_free(key);
110+ return STAT_BOGUS;
111+ }
112+ else
113+ {
114+ a.addr.keytag = keytag;
115+ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
116+ crecp->addr.ds.digest = digest;
117+ crecp->addr.ds.keydata = key;
118+ crecp->addr.ds.algo = algo;
119+ crecp->addr.ds.keytag = keytag;
120+ crecp->addr.ds.keylen = rdlen - 4;
121+ }
122+ }
123+
124+ p = psave;
125+
126+ if (!ADD_RDLEN(header, p, plen, rdlen))
127+ return STAT_BOGUS; /* bad packet */
128+ }
129+
130+ cache_end_insert();
131+ }
132+ }
133+ else
134+ {
135+ int flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
136+ unsigned long minttl = ULONG_MAX;
137+
138+ if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
139+ return STAT_BOGUS;
140+
141 if (RCODE(header) == NXDOMAIN)
142 flags |= F_NXDOMAIN;
143
144@@ -1261,20 +1324,20 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
145 if (!(p = skip_name(p, header, plen, 0)))
146 return STAT_BOGUS;
147
148- GETSHORT(qtype, p);
149- GETSHORT(qclass, p);
150+ GETSHORT(atype, p);
151+ GETSHORT(aclass, p);
152 GETLONG(ttl, p);
153 GETSHORT(rdlen, p);
154-
155+
156 if (!CHECK_LEN(header, p, plen, rdlen))
157 return STAT_BOGUS; /* bad packet */
158-
159- if (qclass != class || qtype != T_SOA)
160+
161+ if (aclass != class || atype != T_SOA)
162 {
163 p += rdlen;
164 continue;
165 }
166-
167+
168 if (ttl < minttl)
169 minttl = ttl;
170
171@@ -1306,7 +1369,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
172 log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "no DS");
173 }
174 }
175-
176+
177 return STAT_OK;
178 }
179
180@@ -2001,11 +2064,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
181 /* Not done, validate now */
182 if (j == i)
183 {
184- int ttl, keytag, algo, digest, sigcnt, rrcnt;
185- unsigned char *psave;
186- struct all_addr a;
187- struct blockdata *key;
188- struct crec *crecp;
189+ int sigcnt, rrcnt;
190 char *wildname;
191
192 if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
193@@ -2032,6 +2091,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
194 Can't overwrite name here. */
195 strcpy(daemon->workspacename, keyname);
196 rc = zone_status(daemon->workspacename, class1, keyname, now);
197+
198 if (rc != STAT_SECURE)
199 {
200 /* Zone is insecure, don't need to validate RRset */
201@@ -2088,65 +2148,6 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
202 if (rc == STAT_BOGUS)
203 return rc;
204 }
205-
206- /* If we just validated a DS RRset, cache it */
207- /* Also note if the RRset is the answer to the question, or the target of a CNAME */
208- cache_start_insert();
209-
210- for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
211- {
212- if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
213- return STAT_BOGUS; /* bad packet */
214-
215- GETSHORT(type2, p2);
216- GETSHORT(class2, p2);
217- GETLONG(ttl, p2);
218- GETSHORT(rdlen2, p2);
219-
220- if (!CHECK_LEN(header, p2, plen, rdlen2))
221- return STAT_BOGUS; /* bad packet */
222-
223- if (class2 == class1 && rc == 1)
224- {
225- psave = p2;
226-
227- if (type1 == T_DS && type2 == T_DS)
228- {
229- if (rdlen2 < 4)
230- return STAT_BOGUS; /* bad packet */
231-
232- GETSHORT(keytag, p2);
233- algo = *p2++;
234- digest = *p2++;
235-
236- /* Cache needs to known class for DNSSEC stuff */
237- a.addr.dnssec.class = class2;
238-
239- if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
240- {
241- if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
242- blockdata_free(key);
243- else
244- {
245- a.addr.keytag = keytag;
246- log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
247- crecp->addr.ds.digest = digest;
248- crecp->addr.ds.keydata = key;
249- crecp->addr.ds.algo = algo;
250- crecp->addr.ds.keytag = keytag;
251- crecp->addr.ds.keylen = rdlen2 - 4;
252- }
253- }
254- }
255-
256- p2 = psave;
257- }
258-
259- if (!ADD_RDLEN(header, p2, plen, rdlen2))
260- return STAT_BOGUS; /* bad packet */
261- }
262-
263- cache_end_insert();
264 }
265 }
266 }
267--
2681.7.10.4
269