]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dnsmasq/017-Abandon_caching_RRSIGs_and_returning_them_from_cache.patch
bird: New package
[ipfire-2.x.git] / src / patches / dnsmasq / 017-Abandon_caching_RRSIGs_and_returning_them_from_cache.patch
CommitLineData
fbcc3cb7
MF
1From 93be5b1e023b0c661e1ec2cd6d811a8ec9055c49 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Tue, 15 Dec 2015 12:04:40 +0000
4Subject: [PATCH] Abandon caching RRSIGs and returning them from cache.
5
6The list of exceptions to being able to locally answer
7cached data for validated records when DNSSEC data is requested
8was getting too long, so don't ever do that. This means
9that the cache no longer has to hold RRSIGS and allows
10us to lose lots of code. Note that cached validated
11answers are still returned as long as do=0
12---
13 src/cache.c | 38 ++---------
14 src/dnsmasq.h | 10 +--
15 src/dnssec.c | 94 ++++-----------------------
16 src/rfc1035.c | 197 ++++++---------------------------------------------------
17 4 files changed, 42 insertions(+), 297 deletions(-)
18
19diff --git a/src/cache.c b/src/cache.c
20index 1b76b67..51ba7cc 100644
21--- a/src/cache.c
22+++ b/src/cache.c
23@@ -189,12 +189,7 @@ static void cache_hash(struct crec *crecp)
24 static void cache_blockdata_free(struct crec *crecp)
25 {
26 if (crecp->flags & F_DNSKEY)
27- {
28- if (crecp->flags & F_DS)
29- blockdata_free(crecp->addr.sig.keydata);
30- else
31- blockdata_free(crecp->addr.key.keydata);
32- }
33+ blockdata_free(crecp->addr.key.keydata);
34 else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
35 blockdata_free(crecp->addr.ds.keydata);
36 }
37@@ -369,13 +364,8 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
38 }
39
40 #ifdef HAVE_DNSSEC
41- /* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also
42- type-covered sensitive for RRSIG */
43- if ((flags & (F_DNSKEY | F_DS)) &&
44- (flags & (F_DNSKEY | F_DS)) == (crecp->flags & (F_DNSKEY | F_DS)) &&
45- crecp->uid == addr->addr.dnssec.class &&
46- (!((flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY)) ||
47- crecp->addr.sig.type_covered == addr->addr.dnssec.type))
48+ /* Deletion has to be class-sensitive for DS and DNSKEY */
49+ if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
50 {
51 if (crecp->flags & F_CONFIG)
52 return crecp;
53@@ -532,13 +522,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
54 struct all_addr free_addr = new->addr.addr;;
55
56 #ifdef HAVE_DNSSEC
57- /* For DNSSEC records, addr holds class and type_covered for RRSIG */
58+ /* For DNSSEC records, addr holds class. */
59 if (new->flags & (F_DS | F_DNSKEY))
60- {
61- free_addr.addr.dnssec.class = new->uid;
62- if ((new->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
63- free_addr.addr.dnssec.type = new->addr.sig.type_covered;
64- }
65+ free_addr.addr.dnssec.class = new->uid;
66 #endif
67
68 free_avail = 1; /* Must be free space now. */
69@@ -653,9 +639,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
70 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
71 {
72 if ((crecp->flags & F_FORWARD) &&
73-#ifdef HAVE_DNSSEC
74- (((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
75-#endif
76 (crecp->flags & prot) &&
77 hostname_isequal(cache_get_name(crecp), name))
78 {
79@@ -713,9 +696,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
80
81 if (ans &&
82 (ans->flags & F_FORWARD) &&
83-#ifdef HAVE_DNSSEC
84- (((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
85-#endif
86 (ans->flags & prot) &&
87 hostname_isequal(cache_get_name(ans), name))
88 return ans;
89@@ -1472,11 +1452,7 @@ void dump_cache(time_t now)
90 #ifdef HAVE_DNSSEC
91 else if (cache->flags & F_DS)
92 {
93- if (cache->flags & F_DNSKEY)
94- /* RRSIG */
95- sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
96- cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
97- else if (!(cache->flags & F_NEG))
98+ if (!(cache->flags & F_NEG))
99 sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
100 cache->addr.ds.algo, cache->addr.ds.digest);
101 }
102@@ -1502,8 +1478,6 @@ void dump_cache(time_t now)
103 else if (cache->flags & F_CNAME)
104 t = "C";
105 #ifdef HAVE_DNSSEC
106- else if ((cache->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
107- t = "G"; /* DNSKEY and DS set -> RRISG */
108 else if (cache->flags & F_DS)
109 t = "S";
110 else if (cache->flags & F_DNSKEY)
111diff --git a/src/dnsmasq.h b/src/dnsmasq.h
112index 023a1cf..4344cae 100644
113--- a/src/dnsmasq.h
114+++ b/src/dnsmasq.h
115@@ -398,14 +398,9 @@ struct crec {
116 unsigned char algo;
117 unsigned char digest;
118 } ds;
119- struct {
120- struct blockdata *keydata;
121- unsigned short keylen, type_covered, keytag;
122- char algo;
123- } sig;
124 } addr;
125 time_t ttd; /* time to die */
126- /* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
127+ /* used as class if DNSKEY/DS, index to source for F_HOSTS */
128 unsigned int uid;
129 unsigned short flags;
130 union {
131@@ -445,8 +440,7 @@ struct crec {
132 #define F_SECSTAT (1u<<24)
133 #define F_NO_RR (1u<<25)
134 #define F_IPSET (1u<<26)
135-#define F_NSIGMATCH (1u<<27)
136-#define F_NOEXTRA (1u<<28)
137+#define F_NOEXTRA (1u<<27)
138
139 /* Values of uid in crecs with F_CONFIG bit set. */
140 #define SRC_INTERFACE 0
141diff --git a/src/dnssec.c b/src/dnssec.c
142index de7b335..1ae03a6 100644
143--- a/src/dnssec.c
144+++ b/src/dnssec.c
145@@ -1004,7 +1004,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
146 {
147 unsigned char *psave, *p = (unsigned char *)(header+1);
148 struct crec *crecp, *recp1;
149- int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag, type_covered;
150+ int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag;
151 struct blockdata *key;
152 struct all_addr a;
153
154@@ -1115,7 +1115,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
155
156 if (valid)
157 {
158- /* DNSKEY RRset determined to be OK, now cache it and the RRsigs that sign it. */
159+ /* DNSKEY RRset determined to be OK, now cache it. */
160 cache_start_insert();
161
162 p = skip_questions(header, plen);
163@@ -1155,7 +1155,10 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
164 if ((key = blockdata_alloc((char*)p, rdlen - 4)))
165 {
166 if (!(recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
167- blockdata_free(key);
168+ {
169+ blockdata_free(key);
170+ return STAT_BOGUS;
171+ }
172 else
173 {
174 a.addr.keytag = keytag;
175@@ -1169,38 +1172,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
176 }
177 }
178 }
179- else if (qtype == T_RRSIG)
180- {
181- /* RRSIG, cache if covers DNSKEY RRset */
182- if (rdlen < 18)
183- return STAT_BOGUS; /* bad packet */
184-
185- GETSHORT(type_covered, p);
186-
187- if (type_covered == T_DNSKEY)
188- {
189- a.addr.dnssec.class = class;
190- a.addr.dnssec.type = type_covered;
191-
192- algo = *p++;
193- p += 13; /* labels, orig_ttl, expiration, inception */
194- GETSHORT(keytag, p);
195- if ((key = blockdata_alloc((char*)psave, rdlen)))
196- {
197- if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
198- blockdata_free(key);
199- else
200- {
201- crecp->addr.sig.keydata = key;
202- crecp->addr.sig.keylen = rdlen;
203- crecp->addr.sig.keytag = keytag;
204- crecp->addr.sig.type_covered = type_covered;
205- crecp->addr.sig.algo = algo;
206- }
207- }
208- }
209- }
210-
211+
212 p = psave;
213 }
214
215@@ -1326,7 +1298,8 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
216 cache_start_insert();
217
218 a.addr.dnssec.class = class;
219- cache_insert(name, &a, now, ttl, flags);
220+ if (!cache_insert(name, &a, now, ttl, flags))
221+ return STAT_BOGUS;
222
223 cache_end_insert();
224
225@@ -2028,14 +2001,13 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
226 /* Not done, validate now */
227 if (j == i)
228 {
229- int ttl, keytag, algo, digest, type_covered, sigcnt, rrcnt;
230+ int ttl, keytag, algo, digest, sigcnt, rrcnt;
231 unsigned char *psave;
232 struct all_addr a;
233 struct blockdata *key;
234 struct crec *crecp;
235 char *wildname;
236- int have_wildcard = 0;
237-
238+
239 if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
240 return STAT_BOGUS;
241
242@@ -2096,8 +2068,6 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
243
244 if (rc == STAT_SECURE_WILDCARD)
245 {
246- have_wildcard = 1;
247-
248 /* An attacker replay a wildcard answer with a different
249 answer and overlay a genuine RR. To prove this
250 hasn't happened, the answer must prove that
251@@ -2119,7 +2089,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
252 return rc;
253 }
254
255- /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
256+ /* If we just validated a DS RRset, cache it */
257 /* Also note if the RRset is the answer to the question, or the target of a CNAME */
258 cache_start_insert();
259
260@@ -2168,45 +2138,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
261 }
262 }
263 }
264- else if (type2 == T_RRSIG)
265- {
266- if (rdlen2 < 18)
267- return STAT_BOGUS; /* bad packet */
268-
269- GETSHORT(type_covered, p2);
270-
271- if (type_covered == type1 &&
272- (type_covered == T_A || type_covered == T_AAAA ||
273- type_covered == T_CNAME || type_covered == T_DS ||
274- type_covered == T_DNSKEY || type_covered == T_PTR))
275- {
276- a.addr.dnssec.type = type_covered;
277- a.addr.dnssec.class = class1;
278-
279- algo = *p2++;
280- p2 += 13; /* labels, orig_ttl, expiration, inception */
281- GETSHORT(keytag, p2);
282-
283- /* We don't cache sigs for wildcard answers, because to reproduce the
284- answer from the cache will require one or more NSEC/NSEC3 records
285- which we don't cache. The lack of the RRSIG ensures that a query for
286- this RRset asking for a secure answer will always be forwarded. */
287- if (!have_wildcard && (key = blockdata_alloc((char*)psave, rdlen2)))
288- {
289- if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DS)))
290- blockdata_free(key);
291- else
292- {
293- crecp->addr.sig.keydata = key;
294- crecp->addr.sig.keylen = rdlen2;
295- crecp->addr.sig.keytag = keytag;
296- crecp->addr.sig.type_covered = type_covered;
297- crecp->addr.sig.algo = algo;
298- }
299- }
300- }
301- }
302-
303+
304 p2 = psave;
305 }
306
307diff --git a/src/rfc1035.c b/src/rfc1035.c
308index 4eb1772..def8fa0 100644
309--- a/src/rfc1035.c
310+++ b/src/rfc1035.c
311@@ -1275,11 +1275,9 @@ int check_for_local_domain(char *name, time_t now)
312 struct naptr *naptr;
313
314 /* Note: the call to cache_find_by_name is intended to find any record which matches
315- ie A, AAAA, CNAME, DS. Because RRSIG records are marked by setting both F_DS and F_DNSKEY,
316- cache_find_by name ordinarily only returns records with an exact match on those bits (ie
317- for the call below, only DS records). The F_NSIGMATCH bit changes this behaviour */
318+ ie A, AAAA, CNAME. */
319
320- if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_DS | F_NO_RR | F_NSIGMATCH)) &&
321+ if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME |F_NO_RR)) &&
322 (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
323 return 1;
324
325@@ -1566,9 +1564,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
326 GETSHORT(flags, pheader);
327
328 if ((sec_reqd = flags & 0x8000))
329- *do_bit = 1;/* do bit */
330+ {
331+ *do_bit = 1;/* do bit */
332+ *ad_reqd = 1;
333+ }
334
335- *ad_reqd = 1;
336 dryrun = 1;
337 }
338
339@@ -1636,98 +1636,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
340 }
341 }
342
343-#ifdef HAVE_DNSSEC
344- if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS))
345- {
346- int gotone = 0;
347- struct blockdata *keydata;
348-
349- /* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */
350- if (sec_reqd)
351- {
352- crecp = NULL;
353- while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
354- if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype)
355- break;
356- }
357-
358- if (!sec_reqd || crecp)
359- {
360- if (qtype == T_DS)
361- {
362- crecp = NULL;
363- while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
364- if (crecp->uid == qclass)
365- {
366- gotone = 1;
367- if (!dryrun)
368- {
369- if (crecp->flags & F_NEG)
370- {
371- if (crecp->flags & F_NXDOMAIN)
372- nxdomain = 1;
373- log_query(F_UPSTREAM, name, NULL, "no DS");
374- }
375- else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
376- {
377- struct all_addr a;
378- a.addr.keytag = crecp->addr.ds.keytag;
379- log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u");
380- if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
381- crec_ttl(crecp, now), &nameoffset,
382- T_DS, qclass, "sbbt",
383- crecp->addr.ds.keytag, crecp->addr.ds.algo,
384- crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata))
385- anscount++;
386-
387- }
388- }
389- }
390- }
391- else /* DNSKEY */
392- {
393- crecp = NULL;
394- while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
395- if (crecp->uid == qclass)
396- {
397- gotone = 1;
398- if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
399- {
400- struct all_addr a;
401- a.addr.keytag = crecp->addr.key.keytag;
402- log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u");
403- if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
404- crec_ttl(crecp, now), &nameoffset,
405- T_DNSKEY, qclass, "sbbt",
406- crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata))
407- anscount++;
408- }
409- }
410- }
411- }
412-
413- /* Now do RRSIGs */
414- if (gotone)
415- {
416- ans = 1;
417- auth = 0;
418- if (!dryrun && sec_reqd)
419- {
420- crecp = NULL;
421- while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
422- if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype &&
423- (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
424- {
425- add_resource_record(header, limit, &trunc, nameoffset, &ansp,
426- crec_ttl(crecp, now), &nameoffset,
427- T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata);
428- anscount++;
429- }
430- }
431- }
432- }
433-#endif
434-
435 if (qclass == C_IN)
436 {
437 struct txt_record *t;
438@@ -1736,6 +1644,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
439 if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
440 {
441 ans = 1;
442+ sec_data = 0;
443 if (!dryrun)
444 {
445 log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
446@@ -1792,6 +1701,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
447
448 if (intr)
449 {
450+ sec_data = 0;
451 ans = 1;
452 if (!dryrun)
453 {
454@@ -1805,6 +1715,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
455 else if (ptr)
456 {
457 ans = 1;
458+ sec_data = 0;
459 if (!dryrun)
460 {
461 log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
462@@ -1819,38 +1730,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
463 }
464 else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
465 {
466- if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
467- {
468- if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
469- crecp = NULL;
470-#ifdef HAVE_DNSSEC
471- else if (crecp->flags & F_DNSSECOK)
472- {
473- int gotsig = 0;
474- struct crec *rr_crec = NULL;
475-
476- while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
477- {
478- if (rr_crec->addr.sig.type_covered == T_PTR && rr_crec->uid == C_IN)
479- {
480- char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
481- gotsig = 1;
482-
483- if (!dryrun &&
484- add_resource_record(header, limit, &trunc, nameoffset, &ansp,
485- rr_crec->ttd - now, &nameoffset,
486- T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata))
487- anscount++;
488- }
489- }
490-
491- if (!gotsig)
492- crecp = NULL;
493- }
494-#endif
495- }
496-
497- if (crecp)
498+ /* Don't use cache when DNSSEC data required. */
499+ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK))
500 {
501 do
502 {
503@@ -1860,19 +1741,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
504
505 if (!(crecp->flags & F_DNSSECOK))
506 sec_data = 0;
507-
508+
509+ ans = 1;
510+
511 if (crecp->flags & F_NEG)
512 {
513- ans = 1;
514 auth = 0;
515 if (crecp->flags & F_NXDOMAIN)
516 nxdomain = 1;
517 if (!dryrun)
518 log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
519 }
520- else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd || option_bool(OPT_DNSSEC_VALID))
521+ else
522 {
523- ans = 1;
524 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
525 auth = 0;
526 if (!dryrun)
527@@ -1892,6 +1773,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
528 else if (is_rev_synth(is_arpa, &addr, name))
529 {
530 ans = 1;
531+ sec_data = 0;
532 if (!dryrun)
533 {
534 log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL);
535@@ -1908,6 +1790,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
536 {
537 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
538 ans = 1;
539+ sec_data = 0;
540 nxdomain = 1;
541 if (!dryrun)
542 log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN,
543@@ -1955,6 +1838,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
544 if (i == 4)
545 {
546 ans = 1;
547+ sec_data = 0;
548 if (!dryrun)
549 {
550 addr.addr.addr4.s_addr = htonl(a);
551@@ -1993,6 +1877,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
552 continue;
553 #endif
554 ans = 1;
555+ sec_data = 0;
556 if (!dryrun)
557 {
558 gotit = 1;
559@@ -2032,48 +1917,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
560 crecp = save;
561 }
562
563- /* If the client asked for DNSSEC and we can't provide RRSIGs, either
564- because we've not doing DNSSEC or the cached answer is signed by negative,
565- don't answer from the cache, forward instead. */
566- if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
567- {
568- if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
569- crecp = NULL;
570-#ifdef HAVE_DNSSEC
571- else if (crecp->flags & F_DNSSECOK)
572- {
573- /* We're returning validated data, need to return the RRSIG too. */
574- struct crec *rr_crec = NULL;
575- int sigtype = type;
576- /* The signature may have expired even though the data is still in cache,
577- forward instead of answering from cache if so. */
578- int gotsig = 0;
579-
580- if (crecp->flags & F_CNAME)
581- sigtype = T_CNAME;
582-
583- while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
584- {
585- if (rr_crec->addr.sig.type_covered == sigtype && rr_crec->uid == C_IN)
586- {
587- char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
588- gotsig = 1;
589-
590- if (!dryrun &&
591- add_resource_record(header, limit, &trunc, nameoffset, &ansp,
592- rr_crec->ttd - now, &nameoffset,
593- T_RRSIG, C_IN, "t", rr_crec->addr.sig.keylen, sigdata))
594- anscount++;
595- }
596- }
597-
598- if (!gotsig)
599- crecp = NULL;
600- }
601-#endif
602- }
603-
604- if (crecp)
605+ /* If the client asked for DNSSEC don't use cached data. */
606+ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK))
607 do
608 {
609 /* don't answer wildcard queries with data not from /etc/hosts
610--
6111.7.10.4
612