]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Abandon caching RRSIGs and returning them from cache.
authorSimon Kelley <simon@thekelleys.org.uk>
Tue, 15 Dec 2015 12:04:40 +0000 (12:04 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Tue, 15 Dec 2015 12:04:40 +0000 (12:04 +0000)
The list of exceptions to being able to locally answer
cached data for validated records when DNSSEC data is requested
was getting too long, so don't ever do that. This means
that the cache no longer has to hold RRSIGS and allows
us to lose lots of code. Note that cached validated
answers are still returned as long as do=0

src/cache.c
src/dnsmasq.h
src/dnssec.c
src/rfc1035.c

index 1b76b6751299939a4cf91e846924c1e38d4f9d43..51ba7cc49889cb84cdcc6ca7ecc69681c7721152 100644 (file)
@@ -189,12 +189,7 @@ static void cache_hash(struct crec *crecp)
 static void cache_blockdata_free(struct crec *crecp)
 {
   if (crecp->flags & F_DNSKEY)
-    {
-      if (crecp->flags & F_DS)
-       blockdata_free(crecp->addr.sig.keydata);
-      else
-       blockdata_free(crecp->addr.key.keydata);
-    }
+    blockdata_free(crecp->addr.key.keydata);
   else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
     blockdata_free(crecp->addr.ds.keydata);
 }
@@ -369,13 +364,8 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
                }
              
 #ifdef HAVE_DNSSEC
-             /* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also 
-                type-covered sensitive for  RRSIG */
-             if ((flags & (F_DNSKEY | F_DS)) &&
-                 (flags & (F_DNSKEY | F_DS)) == (crecp->flags & (F_DNSKEY | F_DS)) &&
-                 crecp->uid == addr->addr.dnssec.class &&
-                 (!((flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY)) || 
-                  crecp->addr.sig.type_covered == addr->addr.dnssec.type))
+             /* Deletion has to be class-sensitive for DS and DNSKEY */
+             if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
                {
                  if (crecp->flags & F_CONFIG)
                    return crecp;
@@ -532,13 +522,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
            struct all_addr free_addr = new->addr.addr;;
 
 #ifdef HAVE_DNSSEC
-           /* For DNSSEC records, addr holds class and type_covered for RRSIG */
+           /* For DNSSEC records, addr holds class. */
            if (new->flags & (F_DS | F_DNSKEY))
-             {
-               free_addr.addr.dnssec.class = new->uid;
-               if ((new->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
-                 free_addr.addr.dnssec.type = new->addr.sig.type_covered;
-             }
+             free_addr.addr.dnssec.class = new->uid;
 #endif
            
            free_avail = 1; /* Must be free space now. */
@@ -653,9 +639,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
          if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
            {
              if ((crecp->flags & F_FORWARD) && 
-#ifdef HAVE_DNSSEC
-                 (((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
-#endif
                  (crecp->flags & prot) &&
                  hostname_isequal(cache_get_name(crecp), name))
                {
@@ -713,9 +696,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
 
   if (ans && 
       (ans->flags & F_FORWARD) &&
-#ifdef HAVE_DNSSEC
-      (((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
-#endif
       (ans->flags & prot) &&     
       hostname_isequal(cache_get_name(ans), name))
     return ans;
@@ -1472,11 +1452,7 @@ void dump_cache(time_t now)
 #ifdef HAVE_DNSSEC
            else if (cache->flags & F_DS)
              {
-               if (cache->flags & F_DNSKEY)
-                 /* RRSIG */
-                 sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
-                         cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
-               else if (!(cache->flags & F_NEG))
+               if (!(cache->flags & F_NEG))
                  sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
                          cache->addr.ds.algo, cache->addr.ds.digest);
              }
@@ -1502,8 +1478,6 @@ void dump_cache(time_t now)
            else if (cache->flags & F_CNAME)
              t = "C";
 #ifdef HAVE_DNSSEC
-           else if ((cache->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
-             t = "G"; /* DNSKEY and DS set -> RRISG */
            else if (cache->flags & F_DS)
              t = "S";
            else if (cache->flags & F_DNSKEY)
index 023a1cfb12f88d1d8321b34e79ebb89bd4c00223..4344cae2061891483a318818a4718ffc5958c4dc 100644 (file)
@@ -398,14 +398,9 @@ struct crec {
       unsigned char algo;
       unsigned char digest; 
     } ds; 
-    struct {
-      struct blockdata *keydata;
-      unsigned short keylen, type_covered, keytag;
-      char algo;
-    } sig;
   } addr;
   time_t ttd; /* time to die */
-  /* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
+  /* used as class if DNSKEY/DS, index to source for F_HOSTS */
   unsigned int uid; 
   unsigned short flags;
   union {
@@ -445,8 +440,7 @@ struct crec {
 #define F_SECSTAT   (1u<<24)
 #define F_NO_RR     (1u<<25)
 #define F_IPSET     (1u<<26)
-#define F_NSIGMATCH (1u<<27)
-#define F_NOEXTRA   (1u<<28)
+#define F_NOEXTRA   (1u<<27)
 
 /* Values of uid in crecs with F_CONFIG bit set. */
 #define SRC_INTERFACE 0
index de7b3358a1ce234de246f1144ce86d4451e95d20..1ae03a6757f4469899c8cd24e009b3e65fd635d7 100644 (file)
@@ -1004,7 +1004,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
 {
   unsigned char *psave, *p = (unsigned char *)(header+1);
   struct crec *crecp, *recp1;
-  int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag, type_covered;
+  int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag;
   struct blockdata *key;
   struct all_addr a;
 
@@ -1115,7 +1115,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
 
   if (valid)
     {
-      /* DNSKEY RRset determined to be OK, now cache it and the RRsigs that sign it. */
+      /* DNSKEY RRset determined to be OK, now cache it. */
       cache_start_insert();
       
       p = skip_questions(header, plen);
@@ -1155,7 +1155,10 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
                  if ((key = blockdata_alloc((char*)p, rdlen - 4)))
                    {
                      if (!(recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
-                       blockdata_free(key);
+                       {
+                         blockdata_free(key);
+                         return STAT_BOGUS;
+                       }
                      else
                        {
                          a.addr.keytag = keytag;
@@ -1169,38 +1172,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
                        }
                    }
                }
-             else if (qtype == T_RRSIG)
-               {
-                 /* RRSIG, cache if covers DNSKEY RRset */
-                 if (rdlen < 18)
-                   return STAT_BOGUS; /* bad packet */
-                 
-                 GETSHORT(type_covered, p);
-                 
-                 if (type_covered == T_DNSKEY)
-                   {
-                     a.addr.dnssec.class = class;
-                     a.addr.dnssec.type = type_covered;
-                     
-                     algo = *p++;
-                     p += 13; /* labels, orig_ttl, expiration, inception */
-                     GETSHORT(keytag, p);      
-                     if ((key = blockdata_alloc((char*)psave, rdlen)))
-                       {
-                         if (!(crecp = cache_insert(name, &a, now, ttl,  F_FORWARD | F_DNSKEY | F_DS)))
-                           blockdata_free(key);
-                         else
-                           {
-                             crecp->addr.sig.keydata = key;
-                             crecp->addr.sig.keylen = rdlen;
-                             crecp->addr.sig.keytag = keytag;
-                             crecp->addr.sig.type_covered = type_covered;
-                             crecp->addr.sig.algo = algo;
-                           }
-                       }
-                   }
-               }
-             
+                     
              p = psave;
            }
 
@@ -1326,7 +1298,8 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
          cache_start_insert();
          
          a.addr.dnssec.class = class;
-         cache_insert(name, &a, now, ttl, flags);
+         if (!cache_insert(name, &a, now, ttl, flags))
+           return STAT_BOGUS;
          
          cache_end_insert();  
          
@@ -2028,14 +2001,13 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
          /* Not done, validate now */
          if (j == i)
            {
-             int ttl, keytag, algo, digest, type_covered, sigcnt, rrcnt;
+             int ttl, keytag, algo, digest, sigcnt, rrcnt;
              unsigned char *psave;
              struct all_addr a;
              struct blockdata *key;
              struct crec *crecp;
              char *wildname;
-             int have_wildcard = 0;
-
+             
              if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
                return STAT_BOGUS;
 
@@ -2096,8 +2068,6 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
                            
                  if (rc == STAT_SECURE_WILDCARD)
                    {
-                     have_wildcard = 1;
-                     
                      /* An attacker replay a wildcard answer with a different
                         answer and overlay a genuine RR. To prove this
                         hasn't happened, the answer must prove that
@@ -2119,7 +2089,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
                        return rc;
                    } 
                  
-                 /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
+                 /* If we just validated a DS RRset, cache it */
                  /* Also note if the RRset is the answer to the question, or the target of a CNAME */
                  cache_start_insert();
                  
@@ -2168,45 +2138,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
                                    } 
                                }
                            }
-                         else if (type2 == T_RRSIG)
-                           {
-                             if (rdlen2 < 18)
-                               return STAT_BOGUS; /* bad packet */
-                             
-                             GETSHORT(type_covered, p2);
-                             
-                             if (type_covered == type1 && 
-                                 (type_covered == T_A || type_covered == T_AAAA ||
-                                  type_covered == T_CNAME || type_covered == T_DS || 
-                                  type_covered == T_DNSKEY || type_covered == T_PTR)) 
-                               {
-                                 a.addr.dnssec.type = type_covered;
-                                 a.addr.dnssec.class = class1;
-                                 
-                                 algo = *p2++;
-                                 p2 += 13; /* labels, orig_ttl, expiration, inception */
-                                 GETSHORT(keytag, p2);
-                                 
-                                 /* We don't cache sigs for wildcard answers, because to reproduce the
-                                    answer from the cache will require one or more NSEC/NSEC3 records 
-                                    which we don't cache. The lack of the RRSIG ensures that a query for
-                                    this RRset asking for a secure answer will always be forwarded. */
-                                 if (!have_wildcard && (key = blockdata_alloc((char*)psave, rdlen2)))
-                                   {
-                                     if (!(crecp = cache_insert(name, &a, now, ttl,  F_FORWARD | F_DNSKEY | F_DS)))
-                                       blockdata_free(key);
-                                     else
-                                       {
-                                         crecp->addr.sig.keydata = key;
-                                         crecp->addr.sig.keylen = rdlen2;
-                                         crecp->addr.sig.keytag = keytag;
-                                         crecp->addr.sig.type_covered = type_covered;
-                                         crecp->addr.sig.algo = algo;
-                                       }
-                                   }
-                               }
-                           }
-                         
+
                          p2 = psave;
                        }
                      
index 4eb1772c07fc27de9d93008e6e1965c35478b261..def8fa0269452beaed5f578c81b95cb8355be915 100644 (file)
@@ -1275,11 +1275,9 @@ int check_for_local_domain(char *name, time_t now)
   struct naptr *naptr;
 
   /* Note: the call to cache_find_by_name is intended to find any record which matches
-     ie A, AAAA, CNAME, DS. Because RRSIG records are marked by setting both F_DS and F_DNSKEY,
-     cache_find_by name ordinarily only returns records with an exact match on those bits (ie
-     for the call below, only DS records). The F_NSIGMATCH bit changes this behaviour */
+     ie A, AAAA, CNAME. */
 
-  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_DS | F_NO_RR | F_NSIGMATCH)) &&
+  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME |F_NO_RR)) &&
       (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
     return 1;
   
@@ -1566,9 +1564,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
       GETSHORT(flags, pheader);
       
       if ((sec_reqd = flags & 0x8000))
-       *do_bit = 1;/* do bit */ 
+       {
+         *do_bit = 1;/* do bit */ 
+         *ad_reqd = 1;
+       }
 
-      *ad_reqd = 1;
       dryrun = 1;
     }
 
@@ -1636,98 +1636,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
            }
        }
 
-#ifdef HAVE_DNSSEC
-      if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS))
-       {
-         int gotone = 0;
-         struct blockdata *keydata;
-
-         /* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */
-         if (sec_reqd)
-           {
-             crecp = NULL;
-             while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
-               if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype)
-                 break;
-           }
-         
-         if (!sec_reqd || crecp)
-           {
-             if (qtype == T_DS)
-               {
-                 crecp = NULL;
-                 while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
-                   if (crecp->uid == qclass)
-                     {
-                       gotone = 1; 
-                       if (!dryrun)
-                         {
-                           if (crecp->flags & F_NEG)
-                             {
-                               if (crecp->flags & F_NXDOMAIN)
-                                 nxdomain = 1;
-                               log_query(F_UPSTREAM, name, NULL, "no DS");     
-                             }
-                           else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
-                             {                                               
-                               struct all_addr a;
-                               a.addr.keytag =  crecp->addr.ds.keytag;
-                               log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u");
-                               if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                       crec_ttl(crecp, now), &nameoffset,
-                                                       T_DS, qclass, "sbbt", 
-                                                       crecp->addr.ds.keytag, crecp->addr.ds.algo, 
-                                                       crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata))
-                                 anscount++;
-                               
-                             } 
-                         }
-                     }
-               }
-             else /* DNSKEY */
-               {
-                 crecp = NULL;
-                 while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
-                   if (crecp->uid == qclass)
-                     {
-                       gotone = 1;
-                       if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
-                         {                                                   
-                           struct all_addr a;
-                           a.addr.keytag =  crecp->addr.key.keytag;
-                           log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u");
-                           if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                   crec_ttl(crecp, now), &nameoffset,
-                                                   T_DNSKEY, qclass, "sbbt", 
-                                                   crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata))
-                             anscount++;
-                         }
-                     }
-               }
-           }
-         
-         /* Now do RRSIGs */
-         if (gotone)
-           {
-             ans = 1;
-             auth = 0;
-             if (!dryrun && sec_reqd)
-               {
-                 crecp = NULL;
-                 while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
-                   if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype &&
-                       (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
-                     {
-                       add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                           crec_ttl(crecp, now), &nameoffset,
-                                           T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata);
-                       anscount++;
-                     }
-               }
-           }
-       }
-#endif      
-      
       if (qclass == C_IN)
        {
          struct txt_record *t;
@@ -1736,6 +1644,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
            if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
              {
                ans = 1;
+               sec_data = 0;
                if (!dryrun)
                  {
                    log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
@@ -1792,6 +1701,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              
              if (intr)
                {
+                 sec_data = 0;
                  ans = 1;
                  if (!dryrun)
                    {
@@ -1805,6 +1715,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              else if (ptr)
                {
                  ans = 1;
+                 sec_data = 0;
                  if (!dryrun)
                    {
                      log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
@@ -1819,38 +1730,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                }
              else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
                {
-                 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
-                   {
-                     if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
-                       crecp = NULL;
-#ifdef HAVE_DNSSEC
-                     else if (crecp->flags & F_DNSSECOK)
-                       {
-                         int gotsig = 0;
-                         struct crec *rr_crec = NULL;
-
-                         while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
-                           {
-                             if (rr_crec->addr.sig.type_covered == T_PTR && rr_crec->uid == C_IN)
-                               {
-                                 char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
-                                 gotsig = 1;
-                                 
-                                 if (!dryrun && 
-                                     add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                         rr_crec->ttd - now, &nameoffset,
-                                                         T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata))
-                                   anscount++;
-                               }
-                           } 
-                         
-                         if (!gotsig)
-                           crecp = NULL;
-                       }
-#endif
-                   }
-
-                 if (crecp)
+                 /* Don't use cache when DNSSEC data required. */
+                 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK))
                    {
                      do 
                        { 
@@ -1860,19 +1741,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                          
                          if (!(crecp->flags & F_DNSSECOK))
                            sec_data = 0;
-                         
+                          
+                         ans = 1;
+                          
                          if (crecp->flags & F_NEG)
                            {
-                             ans = 1;
                              auth = 0;
                              if (crecp->flags & F_NXDOMAIN)
                                nxdomain = 1;
                              if (!dryrun)
                                log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
                            }
-                         else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd || option_bool(OPT_DNSSEC_VALID))
+                         else
                            {
-                             ans = 1;
                              if (!(crecp->flags & (F_HOSTS | F_DHCP)))
                                auth = 0;
                              if (!dryrun)
@@ -1892,6 +1773,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
              else if (is_rev_synth(is_arpa, &addr, name))
                {
                  ans = 1;
+                 sec_data = 0;
                  if (!dryrun)
                    {
                      log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL); 
@@ -1908,6 +1790,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                {
                  /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
                  ans = 1;
+                 sec_data = 0;
                  nxdomain = 1;
                  if (!dryrun)
                    log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, 
@@ -1955,6 +1838,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                  if (i == 4)
                    {
                      ans = 1;
+                     sec_data = 0;
                      if (!dryrun)
                        {
                          addr.addr.addr4.s_addr = htonl(a);
@@ -1993,6 +1877,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                                continue;
 #endif 
                              ans = 1;  
+                             sec_data = 0;
                              if (!dryrun)
                                {
                                  gotit = 1;
@@ -2032,48 +1917,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
                      crecp = save;
                    }
 
-                 /* If the client asked for DNSSEC and we can't provide RRSIGs, either
-                    because we've not doing DNSSEC or the cached answer is signed by negative,
-                    don't answer from the cache, forward instead. */
-                 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
-                   {
-                     if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
-                       crecp = NULL;
-#ifdef HAVE_DNSSEC
-                     else if (crecp->flags & F_DNSSECOK)
-                       {
-                         /* We're returning validated data, need to return the RRSIG too. */
-                         struct crec *rr_crec = NULL;
-                         int sigtype = type;
-                         /* The signature may have expired even though the data is still in cache, 
-                            forward instead of answering from cache if so. */
-                         int gotsig = 0;
-                         
-                         if (crecp->flags & F_CNAME)
-                           sigtype = T_CNAME;
-                         
-                         while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
-                           {
-                             if (rr_crec->addr.sig.type_covered == sigtype && rr_crec->uid == C_IN)
-                               {
-                                 char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
-                                 gotsig = 1;
-                                 
-                                 if (!dryrun && 
-                                     add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-                                                         rr_crec->ttd - now, &nameoffset,
-                                                         T_RRSIG, C_IN, "t", rr_crec->addr.sig.keylen, sigdata))
-                                   anscount++;
-                               }
-                           }
-                         
-                         if (!gotsig)
-                           crecp = NULL;
-                       }
-#endif
-                   }            
-
-                 if (crecp)
+                 /* If the client asked for DNSSEC  don't use cached data. */
+                 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK))
                    do
                      { 
                        /* don't answer wildcard queries with data not from /etc/hosts