Browse Source

avoid using RRsetList::operator[] because it implicitly (and naively) assumes
the class is IN. Added a test case where this assumption could trigger a
catastrophic result.


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1422 e5f2f494-b856-4b98-b285-d166d9295462

JINMEI Tatuya 15 years ago
parent
commit
dd57e92f92
2 changed files with 38 additions and 14 deletions
  1. 21 14
      src/lib/auth/data_source.cc
  2. 17 0
      src/lib/auth/tests/datasrc_unittest.cc

+ 21 - 14
src/lib/auth/data_source.cc

@@ -232,16 +232,19 @@ hasDelegation(const DataSrc* ds, const Name* zonename, Query& q,
         // Found a referral while getting answer data;
         // send a delegation.
         if (found) {
-            if (RRsetPtr r = ref[RRType::DNAME()]) {
+            RRsetPtr r = ref.findRRset(RRType::DNAME(), q.qclass());
+            if (r != NULL) {
                 RRsetList syn;
                 q.message().addRRset(Section::ANSWER(), r, q.wantDnssec());
                 q.message().setHeaderFlag(MessageFlag::AA());
                 synthesizeCname(task, r, syn);
                 if (syn.size() == 1) {
                     q.message().addRRset(Section::ANSWER(),
-                                         syn[RRType::CNAME()],
+                                         syn.findRRset(RRType::CNAME(),
+                                                       q.qclass()),
                                          q.wantDnssec());
-                    chaseCname(q, task, syn[RRType::CNAME()]);
+                    chaseCname(q, task, syn.findRRset(RRType::CNAME(),
+                                                      q.qclass()));
                     return (true);
                 }
             }
@@ -274,7 +277,8 @@ addSOA(Query& q, const Name* zonename, const DataSrc* ds) {
         return (DataSrc::ERROR);
     }
 
-    m.addRRset(Section::AUTHORITY(), soa[RRType::SOA()], q.wantDnssec());
+    m.addRRset(Section::AUTHORITY(), soa.findRRset(RRType::SOA(), q.qclass()),
+               q.wantDnssec());
     return (DataSrc::SUCCESS);
 }
 
@@ -289,19 +293,20 @@ addNSEC(Query& q, const QueryTaskPtr task, const Name& name,
                       QueryTask::SIMPLE_QUERY); 
     RETERR(doQueryTask(ds, &zonename, newtask, nsec));
     if (newtask.flags == 0) {
-        m.addRRset(Section::AUTHORITY(), nsec[RRType::NSEC()], true);
+        m.addRRset(Section::AUTHORITY(), nsec.findRRset(RRType::NSEC(),
+                                                        q.qclass()), true);
     }
 
     return (DataSrc::SUCCESS);
 }
 
 static inline DataSrc::Result
-getNsec3(const DataSrc* ds, const Name& zonename, string& hash, 
-         RRsetPtr& target)
+getNsec3(const DataSrc* ds, const Name& zonename, const RRClass& qclass,
+         string& hash, RRsetPtr& target)
 {
     RRsetList rl;
     RETERR(ds->findCoveringNSEC3(zonename, hash, rl));
-    target = rl[RRType::NSEC3()];
+    target = rl.findRRset(RRType::NSEC3(), qclass);
     return (DataSrc::SUCCESS);
 }
 
@@ -318,7 +323,7 @@ getNsec3Param(Query& q, const DataSrc* ds, const Name& zonename) {
         return (ConstNsec3ParamPtr());
     }
 
-    RRsetPtr rrset = nsec3param[RRType::NSEC3PARAM()];
+    RRsetPtr rrset = nsec3param.findRRset(RRType::NSEC3PARAM(), q.qclass());
     if (!rrset) {
         return (ConstNsec3ParamPtr());
     }
@@ -347,7 +352,7 @@ proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, const Name& zonename)
         // Attach the NSEC3 record covering the QNAME
         RRsetPtr rrset;
         string hash1(nsec3->getHash(task->qname)), hash2;
-        RETERR(getNsec3(ds, zonename, hash1, rrset));
+        RETERR(getNsec3(ds, zonename, q.qclass(), hash1, rrset));
         m.addRRset(Section::AUTHORITY(), rrset, true);
 
         // If this is an NXRRSET or NOERROR/NODATA, we're done
@@ -370,7 +375,7 @@ proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, const Name& zonename)
 
             // hash2 will be overwritten with the actual hash found;
             // we don't want to use one until we find an exact match
-            RETERR(getNsec3(ds, zonename, hash2, rrset));
+            RETERR(getNsec3(ds, zonename, q.qclass(), hash2, rrset));
             if (hash2 == nodehash) {
                 m.addRRset(Section::AUTHORITY(), rrset, true);
                 break;
@@ -380,7 +385,7 @@ proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, const Name& zonename)
         // Now add a covering NSEC3 for a wildcard under the
         // closest provable enclosing name
         string hash3(nsec3->getHash(Name("*").concatenate(enclosure)));
-        RETERR(getNsec3(ds, zonename, hash3, rrset));
+        RETERR(getNsec3(ds, zonename, q.qclass(), hash3, rrset));
         if (hash3 != hash1 && hash3 != hash2) {
             m.addRRset(Section::AUTHORITY(), rrset, true);
         }
@@ -453,7 +458,8 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds,
     // add authority.
     if (found) {
         if ((rflags & DataSrc::CNAME_FOUND) != 0) {
-            if (RRsetPtr rrset = wild[RRType::CNAME()]) {
+            RRsetPtr rrset = wild.findRRset(RRType::CNAME(), q.qclass());
+            if (rrset != NULL) {
                 rrset->setName(task->qname);
                 m.addRRset(Section::ANSWER(), rrset, q.wantDnssec());
                 chaseCname(q, task, rrset);
@@ -611,7 +617,8 @@ DataSrc::doQuery(Query& q)
         } else if ((task->flags & CNAME_FOUND) != 0) {
             // The qname node contains a CNAME.  Add a new task to the
             // queue to look up its target.
-            if (RRsetPtr rrset = data[RRType::CNAME()]) {
+            RRsetPtr rrset = data.findRRset(RRType::CNAME(), q.qclass());
+            if (rrset != NULL) {
                 m.addRRset(task->section, rrset, q.wantDnssec());
                 chaseCname(q, task, rrset);
             }

+ 17 - 0
src/lib/auth/tests/datasrc_unittest.cc

@@ -36,6 +36,7 @@
 
 #include <auth/query.h>
 #include <auth/sqlite3_datasrc.h>
+#include <auth/static_datasrc.h>
 
 #include "unittest_util.h"
 #include "test_datasrc.h"
@@ -58,8 +59,10 @@ protected:
         sql3_source->init(SQLITE_DBFILE_EXAMPLE);
         DataSrcPtr test_source = DataSrcPtr(new TestDataSrc);
         test_source->init();
+        DataSrcPtr static_source = DataSrcPtr(new StaticDataSrc);
         meta_source.addDataSrc(test_source);
         meta_source.addDataSrc(sql3_source);
+        meta_source.addDataSrc(static_source);
     }
     void QueryCommon(const RRClass& qclass);
     void readAndProcessQuery(const char* datafile);
@@ -719,6 +722,20 @@ TEST_F(DataSrcTest, RootDSQuery) {
 }
 #endif
 
+// Non-existent name in the "static" data source.  The purpose of this test
+// is to check a corner case behavior when atypical RRClass (CH in this case)
+// is specified.
+TEST_F(DataSrcTest, StaticNxDomain) {
+    createAndProcessQuery(Name("www.version.bind"), RRClass::CH(),
+                          RRType::TXT());
+    headerCheck(msg, Rcode::NXDOMAIN(), true, true, true, 0, 1, 0);
+    RRsetIterator rit = msg.beginSection(Section::AUTHORITY());
+    RRsetPtr rrset = *rit;
+    EXPECT_EQ(Name("version.bind"), rrset->getName());
+    EXPECT_EQ(RRType::SOA(), rrset->getType());
+    EXPECT_EQ(RRClass::CH(), rrset->getClass());
+}
+
 TEST_F(DataSrcTest, Nsec3Hash) {
     vector<uint8_t> salt;
     salt.push_back(0xfe);