memory_datasrc_unittest.cc 98 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include "faked_nsec3.h"
  15. #include <exceptions/exceptions.h>
  16. #include <dns/masterload.h>
  17. #include <dns/name.h>
  18. #include <dns/nsec3hash.h>
  19. #include <dns/rdata.h>
  20. #include <dns/rdataclass.h>
  21. #include <dns/rrclass.h>
  22. #include <dns/rrsetlist.h>
  23. #include <dns/rrttl.h>
  24. #include <dns/masterload.h>
  25. #include <datasrc/client.h>
  26. #include <datasrc/memory_datasrc.h>
  27. #include <datasrc/data_source.h>
  28. #include <datasrc/iterator.h>
  29. #include "test_client.h"
  30. #include <testutils/dnsmessage_test.h>
  31. #include <gtest/gtest.h>
  32. #include <boost/bind.hpp>
  33. #include <boost/foreach.hpp>
  34. #include <boost/shared_ptr.hpp>
  35. #include <sstream>
  36. #include <vector>
  37. using namespace std;
  38. using namespace isc::dns;
  39. using namespace isc::dns::rdata;
  40. using namespace isc::datasrc;
  41. using namespace isc::testutils;
  42. using boost::shared_ptr;
  43. using namespace isc::datasrc::test;
  44. namespace {
  45. // Commonly used result codes (Who should write the prefix all the time)
  46. using result::SUCCESS;
  47. using result::EXIST;
  48. class InMemoryClientTest : public ::testing::Test {
  49. protected:
  50. InMemoryClientTest() : rrclass(RRClass::IN())
  51. {}
  52. RRClass rrclass;
  53. InMemoryClient memory_client;
  54. };
  55. TEST_F(InMemoryClientTest, add_find_Zone) {
  56. // test add zone
  57. // Bogus zone (NULL)
  58. EXPECT_THROW(memory_client.addZone(ZoneFinderPtr()),
  59. isc::InvalidParameter);
  60. // add zones with different names one by one
  61. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  62. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  63. Name("a")))));
  64. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  65. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  66. Name("b")))));
  67. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  68. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  69. Name("c")))));
  70. // add zones with the same name suffix
  71. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  72. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  73. Name("x.d.e.f")))));
  74. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  75. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  76. Name("o.w.y.d.e.f")))));
  77. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  78. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  79. Name("p.w.y.d.e.f")))));
  80. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  81. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  82. Name("q.w.y.d.e.f")))));
  83. // add super zone and its subzone
  84. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  85. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  86. Name("g.h")))));
  87. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  88. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  89. Name("i.g.h")))));
  90. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  91. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  92. Name("z.d.e.f")))));
  93. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  94. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  95. Name("j.z.d.e.f")))));
  96. // different zone class isn't allowed.
  97. EXPECT_EQ(result::EXIST, memory_client.addZone(
  98. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  99. Name("q.w.y.d.e.f")))));
  100. // names are compared in a case insensitive manner.
  101. EXPECT_EQ(result::EXIST, memory_client.addZone(
  102. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  103. Name("Q.W.Y.d.E.f")))));
  104. // test find zone
  105. EXPECT_EQ(result::SUCCESS, memory_client.findZone(Name("a")).code);
  106. EXPECT_EQ(Name("a"),
  107. memory_client.findZone(Name("a")).zone_finder->getOrigin());
  108. EXPECT_EQ(result::SUCCESS,
  109. memory_client.findZone(Name("j.z.d.e.f")).code);
  110. EXPECT_EQ(Name("j.z.d.e.f"),
  111. memory_client.findZone(Name("j.z.d.e.f")).zone_finder->
  112. getOrigin());
  113. // NOTFOUND
  114. EXPECT_EQ(result::NOTFOUND, memory_client.findZone(Name("d.e.f")).code);
  115. EXPECT_EQ(ConstZoneFinderPtr(),
  116. memory_client.findZone(Name("d.e.f")).zone_finder);
  117. EXPECT_EQ(result::NOTFOUND,
  118. memory_client.findZone(Name("w.y.d.e.f")).code);
  119. EXPECT_EQ(ConstZoneFinderPtr(),
  120. memory_client.findZone(Name("w.y.d.e.f")).zone_finder);
  121. // there's no exact match. the result should be the longest match,
  122. // and the code should be PARTIALMATCH.
  123. EXPECT_EQ(result::PARTIALMATCH,
  124. memory_client.findZone(Name("j.g.h")).code);
  125. EXPECT_EQ(Name("g.h"),
  126. memory_client.findZone(Name("g.h")).zone_finder->getOrigin());
  127. EXPECT_EQ(result::PARTIALMATCH,
  128. memory_client.findZone(Name("z.i.g.h")).code);
  129. EXPECT_EQ(Name("i.g.h"),
  130. memory_client.findZone(Name("z.i.g.h")).zone_finder->
  131. getOrigin());
  132. }
  133. TEST_F(InMemoryClientTest, iterator) {
  134. // Just some preparations of data
  135. boost::shared_ptr<InMemoryZoneFinder>
  136. zone(new InMemoryZoneFinder(RRClass::IN(), Name("a")));
  137. RRsetPtr aRRsetA(new RRset(Name("a"), RRClass::IN(), RRType::A(),
  138. RRTTL(300)));
  139. aRRsetA->addRdata(rdata::in::A("192.0.2.1"));
  140. RRsetPtr aRRsetAAAA(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  141. RRTTL(300)));
  142. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::1"));
  143. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::2"));
  144. RRsetPtr subRRsetA(new RRset(Name("sub.x.a"), RRClass::IN(), RRType::A(),
  145. RRTTL(300)));
  146. subRRsetA->addRdata(rdata::in::A("192.0.2.2"));
  147. EXPECT_EQ(result::SUCCESS, memory_client.addZone(zone));
  148. // First, the zone is not there, so it should throw
  149. EXPECT_THROW(memory_client.getIterator(Name("b")), DataSourceError);
  150. // This zone is not there either, even when there's a zone containing this
  151. EXPECT_THROW(memory_client.getIterator(Name("x.a")), DataSourceError);
  152. // Now, an empty zone
  153. ZoneIteratorPtr iterator(memory_client.getIterator(Name("a")));
  154. EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
  155. // It throws Unexpected when we are past the end
  156. EXPECT_THROW(iterator->getNextRRset(), isc::Unexpected);
  157. EXPECT_EQ(result::SUCCESS, zone->add(aRRsetA));
  158. EXPECT_EQ(result::SUCCESS, zone->add(aRRsetAAAA));
  159. EXPECT_EQ(result::SUCCESS, zone->add(subRRsetA));
  160. // Check it with full zone.
  161. vector<ConstRRsetPtr> expected_rrsets;
  162. expected_rrsets.push_back(aRRsetA);
  163. expected_rrsets.push_back(aRRsetAAAA);
  164. expected_rrsets.push_back(subRRsetA);
  165. iterator = memory_client.getIterator(Name("a"));
  166. vector<ConstRRsetPtr> actual_rrsets;
  167. ConstRRsetPtr actual;
  168. while ((actual = iterator->getNextRRset()) != NULL) {
  169. actual_rrsets.push_back(actual);
  170. }
  171. rrsetsCheck(expected_rrsets.begin(), expected_rrsets.end(),
  172. actual_rrsets.begin(), actual_rrsets.end());
  173. }
  174. TEST_F(InMemoryClientTest, iterator_separate_rrs) {
  175. // Exactly the same tests as for iterator, but now with separate_rrs = true
  176. // For the one that returns actual data, the AAAA should now be split up
  177. boost::shared_ptr<InMemoryZoneFinder>
  178. zone(new InMemoryZoneFinder(RRClass::IN(), Name("a")));
  179. RRsetPtr aRRsetA(new RRset(Name("a"), RRClass::IN(), RRType::A(),
  180. RRTTL(300)));
  181. aRRsetA->addRdata(rdata::in::A("192.0.2.1"));
  182. RRsetPtr aRRsetAAAA(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  183. RRTTL(300)));
  184. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::1"));
  185. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::2"));
  186. RRsetPtr aRRsetAAAA_r1(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  187. RRTTL(300)));
  188. aRRsetAAAA_r1->addRdata(rdata::in::AAAA("2001:db8::1"));
  189. RRsetPtr aRRsetAAAA_r2(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  190. RRTTL(300)));
  191. aRRsetAAAA_r2->addRdata(rdata::in::AAAA("2001:db8::2"));
  192. RRsetPtr subRRsetA(new RRset(Name("sub.x.a"), RRClass::IN(), RRType::A(),
  193. RRTTL(300)));
  194. subRRsetA->addRdata(rdata::in::A("192.0.2.2"));
  195. EXPECT_EQ(result::SUCCESS, memory_client.addZone(zone));
  196. // First, the zone is not there, so it should throw
  197. EXPECT_THROW(memory_client.getIterator(Name("b"), true), DataSourceError);
  198. // This zone is not there either, even when there's a zone containing this
  199. EXPECT_THROW(memory_client.getIterator(Name("x.a")), DataSourceError);
  200. // Now, an empty zone
  201. ZoneIteratorPtr iterator(memory_client.getIterator(Name("a"), true));
  202. EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
  203. // It throws Unexpected when we are past the end
  204. EXPECT_THROW(iterator->getNextRRset(), isc::Unexpected);
  205. ASSERT_EQ(result::SUCCESS, zone->add(aRRsetA));
  206. ASSERT_EQ(result::SUCCESS, zone->add(aRRsetAAAA));
  207. ASSERT_EQ(result::SUCCESS, zone->add(subRRsetA));
  208. // Check it with full zone, one by one.
  209. // It should be in ascending order in case of InMemory data source
  210. // (isn't guaranteed in general)
  211. iterator = memory_client.getIterator(Name("a"), true);
  212. EXPECT_EQ(aRRsetA->toText(), iterator->getNextRRset()->toText());
  213. EXPECT_EQ(aRRsetAAAA_r1->toText(), iterator->getNextRRset()->toText());
  214. EXPECT_EQ(aRRsetAAAA_r2->toText(), iterator->getNextRRset()->toText());
  215. EXPECT_EQ(subRRsetA->toText(), iterator->getNextRRset()->toText());
  216. EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
  217. }
  218. TEST_F(InMemoryClientTest, getZoneCount) {
  219. EXPECT_EQ(0, memory_client.getZoneCount());
  220. memory_client.addZone(
  221. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  222. Name("example.com"))));
  223. EXPECT_EQ(1, memory_client.getZoneCount());
  224. // duplicate add. counter shouldn't change
  225. memory_client.addZone(
  226. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  227. Name("example.com"))));
  228. EXPECT_EQ(1, memory_client.getZoneCount());
  229. // add one more
  230. memory_client.addZone(
  231. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  232. Name("example.org"))));
  233. EXPECT_EQ(2, memory_client.getZoneCount());
  234. }
  235. TEST_F(InMemoryClientTest, startUpdateZone) {
  236. EXPECT_THROW(memory_client.getUpdater(Name("example.org"), false),
  237. isc::NotImplemented);
  238. }
  239. // Commonly used RRSIG data
  240. const char* const rrsig_a_txt =
  241. "example.org. 300 IN RRSIG A 5 3 3600 20000101000000 20000201000000 12345 "
  242. "example.org. FAKEFAKEFAKE\n";
  243. const char* const rrsig_ns_txt =
  244. "example.org. 300 IN RRSIG NS 5 3 3600 20000101000000 20000201000000 "
  245. "54321 example.org. FAKEFAKEFAKEFAKE\n";
  246. // This RRset has two RRSIGs
  247. const char* const rrsig_aaaa_txt =
  248. "ns.example.org. 300 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
  249. "12345 example.org. FAKEFAKEFAKE\n"
  250. "ns.example.org. 300 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
  251. "54321 example.org. FAKEFAKEFAKEFAKE\n";
  252. // A helper callback of masterLoad() used in InMemoryZoneFinderTest.
  253. void
  254. setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
  255. *(*it) = rrset;
  256. ++it;
  257. }
  258. // Some faked NSEC3 hash values commonly used in tests and the faked NSEC3Hash
  259. // object.
  260. //
  261. // For apex (example.org)
  262. const char* const apex_hash = "0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  263. const char* const apex_hash_lower = "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom";
  264. // For ns1.example.org
  265. const char* const ns1_hash = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR";
  266. // For w.example.org
  267. const char* const w_hash = "01UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
  268. // For x.y.w.example.org (lower-cased)
  269. const char* const xyw_hash = "2vptu5timamqttgl4luu9kg21e0aor3s";
  270. // For zzz.example.org.
  271. const char* const zzz_hash = "R53BQ7CC2UVMUBFU5OCMM6PERS9TK9EN";
  272. // A simple faked NSEC3 hash calculator with a dedicated creator for it.
  273. //
  274. // This is used in some NSEC3-related tests below.
  275. class TestNSEC3HashCreator : public NSEC3HashCreator {
  276. class TestNSEC3Hash : public NSEC3Hash {
  277. private:
  278. typedef map<Name, string> NSEC3HashMap;
  279. typedef NSEC3HashMap::value_type NSEC3HashPair;
  280. NSEC3HashMap map_;
  281. public:
  282. TestNSEC3Hash() {
  283. // Build pre-defined hash
  284. map_[Name("example.org")] = apex_hash;
  285. map_[Name("www.example.org")] = "2S9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  286. map_[Name("xxx.example.org")] = "Q09MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  287. map_[Name("yyy.example.org")] = "0A9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  288. map_[Name("x.y.w.example.org")] =
  289. "2VPTU5TIMAMQTTGL4LUU9KG21E0AOR3S";
  290. map_[Name("y.w.example.org")] = "K8UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
  291. map_[Name("w.example.org")] = w_hash;
  292. map_[Name("zzz.example.org")] = zzz_hash;
  293. map_[Name("smallest.example.org")] =
  294. "00000000000000000000000000000000";
  295. map_[Name("largest.example.org")] =
  296. "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU";
  297. }
  298. virtual string calculate(const Name& name) const {
  299. const NSEC3HashMap::const_iterator found = map_.find(name);
  300. if (found != map_.end()) {
  301. return (found->second);
  302. }
  303. isc_throw(isc::Unexpected, "unexpected name for NSEC3 test: "
  304. << name);
  305. }
  306. virtual bool match(const generic::NSEC3PARAM&) const {
  307. return (true);
  308. }
  309. virtual bool match(const generic::NSEC3&) const {
  310. return (true);
  311. }
  312. };
  313. public:
  314. virtual NSEC3Hash* create(const generic::NSEC3PARAM&) const {
  315. return (new TestNSEC3Hash);
  316. }
  317. virtual NSEC3Hash* create(const generic::NSEC3&) const {
  318. return (new TestNSEC3Hash);
  319. }
  320. virtual NSEC3Hash* create(uint8_t, uint16_t,
  321. const vector<uint8_t>&) const {
  322. return (new TestNSEC3Hash);
  323. }
  324. };
  325. /// \brief Test fixture for the InMemoryZoneFinder class
  326. class InMemoryZoneFinderTest : public ::testing::Test {
  327. // A straightforward pair of textual RR(set) and a RRsetPtr variable
  328. // to store the RRset. Used to build test data below.
  329. struct RRsetData {
  330. const char* const text; // textual representation of an RRset
  331. RRsetPtr* rrset;
  332. };
  333. protected:
  334. // The following sub tests are shared by multiple test cases, changing
  335. // the zone's DNSSEC status (unsigned, NSEC-signed or NSEC3-signed).
  336. // expected_flags is set to either RESULT_NSEC_SIGNED or
  337. // RESULT_NSEC3_SIGNED when it's NSEC/NSEC3 signed respectively and
  338. // find() is expected to set the corresponding flags.
  339. // find_options should be set to FIND_DNSSEC for NSEC-signed case when
  340. // NSEC is expected to be returned.
  341. void findCheck(ZoneFinder::FindResultFlags expected_flags =
  342. ZoneFinder::RESULT_DEFAULT,
  343. ZoneFinder::FindOptions find_options =
  344. ZoneFinder::FIND_DEFAULT);
  345. void emptyNodeCheck(ZoneFinder::FindResultFlags expected_flags =
  346. ZoneFinder::RESULT_DEFAULT);
  347. void wildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  348. ZoneFinder::RESULT_DEFAULT,
  349. ZoneFinder::FindOptions find_options =
  350. ZoneFinder::FIND_DEFAULT);
  351. void doCancelWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  352. ZoneFinder::RESULT_DEFAULT,
  353. ZoneFinder::FindOptions find_options =
  354. ZoneFinder::FIND_DEFAULT);
  355. void anyWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  356. ZoneFinder::RESULT_DEFAULT);
  357. void emptyWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  358. ZoneFinder::RESULT_DEFAULT);
  359. void findNSECENTCheck(const Name& ent_name,
  360. ConstRRsetPtr expected_nsec,
  361. ZoneFinder::FindResultFlags expected_flags =
  362. ZoneFinder::RESULT_DEFAULT);
  363. public:
  364. InMemoryZoneFinderTest() :
  365. class_(RRClass::IN()),
  366. origin_("example.org"),
  367. zone_finder_(class_, origin_)
  368. {
  369. // Build test RRsets. Below, we construct an RRset for
  370. // each textual RR(s) of zone_data, and assign it to the corresponding
  371. // rr_xxx.
  372. // Note that this contains an out-of-zone RR, and due to the
  373. // validation check of masterLoad() used below, we cannot add SOA.
  374. const RRsetData zone_data[] = {
  375. {"example.org. 300 IN NS ns.example.org.", &rr_ns_},
  376. {"example.org. 300 IN A 192.0.2.1", &rr_a_},
  377. {"ns.example.org. 300 IN A 192.0.2.2", &rr_ns_a_},
  378. {"ns.example.org. 300 IN AAAA 2001:db8::2", &rr_ns_aaaa_},
  379. {"cname.example.org. 300 IN CNAME canonical.example.org",
  380. &rr_cname_},
  381. {"cname.example.org. 300 IN A 192.0.2.3", &rr_cname_a_},
  382. {"dname.example.org. 300 IN DNAME target.example.org.",
  383. &rr_dname_},
  384. {"dname.example.org. 300 IN A 192.0.2.39", &rr_dname_a_},
  385. {"dname.example.org. 300 IN NS ns.dname.example.org.",
  386. &rr_dname_ns_},
  387. {"example.org. 300 IN DNAME example.com.", &rr_dname_apex_},
  388. {"child.example.org. 300 IN NS ns.child.example.org.",
  389. &rr_child_ns_},
  390. {"child.example.org. 300 IN DS 12345 5 1 DEADBEEF",
  391. &rr_child_ds_},
  392. {"ns.child.example.org. 300 IN A 192.0.2.153",
  393. &rr_child_glue_},
  394. {"grand.child.example.org. 300 IN NS ns.grand.child.example.org.",
  395. &rr_grandchild_ns_},
  396. {"ns.grand.child.example.org. 300 IN AAAA 2001:db8::253",
  397. &rr_grandchild_glue_},
  398. {"dname.child.example.org. 300 IN DNAME example.com.",
  399. &rr_child_dname_},
  400. {"example.com. 300 IN A 192.0.2.10", &rr_out_},
  401. {"*.wild.example.org. 300 IN A 192.0.2.1", &rr_wild_},
  402. {"*.cnamewild.example.org. 300 IN CNAME canonial.example.org.",
  403. &rr_cnamewild_},
  404. {"foo.wild.example.org. 300 IN A 192.0.2.3", &rr_under_wild_},
  405. {"wild.*.foo.example.org. 300 IN A 192.0.2.1", &rr_emptywild_},
  406. {"wild.*.foo.*.bar.example.org. 300 IN A 192.0.2.1",
  407. &rr_nested_emptywild_},
  408. {"*.nswild.example.org. 300 IN NS nswild.example.", &rr_nswild_},
  409. {"*.dnamewild.example.org. 300 IN DNAME dnamewild.example.",
  410. &rr_dnamewild_},
  411. {"*.child.example.org. 300 IN A 192.0.2.1", &rr_child_wild_},
  412. {"bar.foo.wild.example.org. 300 IN A 192.0.2.2", &rr_not_wild_},
  413. {"baz.foo.wild.example.org. 300 IN A 192.0.2.3",
  414. &rr_not_wild_another_},
  415. {"0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM.example.org. 300 IN "
  416. "NSEC3 1 1 12 aabbccdd 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG",
  417. &rr_nsec3_},
  418. {"example.org. 300 IN NSEC wild.*.foo.example.org. "
  419. "NS SOA RRSIG NSEC DNSKEY", &rr_nsec_},
  420. // Together with the apex NSEC, these next NSECs make a complete
  421. // chain in the case of the zone for the emptyNonterminal tests
  422. // (We may want to clean up this generator code and/or masterLoad
  423. // so that we can prepare conflicting datasets better)
  424. {"wild.*.foo.example.org. 3600 IN NSEC ns.example.org. "
  425. "A RRSIG NSEC", &rr_ent_nsec2_},
  426. {"ns.example.org. 3600 IN NSEC foo.wild.example.org. A RRSIG NSEC",
  427. &rr_ent_nsec3_},
  428. {"foo.wild.example.org. 3600 IN NSEC example.org. A RRSIG NSEC",
  429. &rr_ent_nsec4_},
  430. // And these are NSECs used in different tests
  431. {"ns.example.org. 300 IN NSEC *.nswild.example.org. A AAAA NSEC",
  432. &rr_ns_nsec_},
  433. {"*.wild.example.org. 300 IN NSEC foo.wild.example.org. A NSEC",
  434. &rr_wild_nsec_},
  435. {NULL, NULL}
  436. };
  437. stringstream zone_data_stream;
  438. vector<RRsetPtr*> rrsets;
  439. for (unsigned int i = 0; zone_data[i].text != NULL; ++i) {
  440. zone_data_stream << zone_data[i].text << "\n";
  441. rrsets.push_back(zone_data[i].rrset);
  442. }
  443. masterLoad(zone_data_stream, Name::ROOT_NAME(), class_,
  444. boost::bind(setRRset, _1, rrsets.begin()));
  445. }
  446. ~InMemoryZoneFinderTest() {
  447. // Make sure we reset the hash creator to the default
  448. setNSEC3HashCreator(NULL);
  449. }
  450. // Some data to test with
  451. const RRClass class_;
  452. const Name origin_;
  453. // The zone finder to torture by tests
  454. InMemoryZoneFinder zone_finder_;
  455. // Placeholder for storing RRsets to be checked with rrsetsCheck()
  456. vector<ConstRRsetPtr> actual_rrsets_;
  457. /*
  458. * Some RRsets to put inside the zone.
  459. */
  460. RRsetPtr
  461. // Out of zone RRset
  462. rr_out_,
  463. // NS of example.org
  464. rr_ns_,
  465. // A of ns.example.org
  466. rr_ns_a_,
  467. // AAAA of ns.example.org
  468. rr_ns_aaaa_,
  469. // A of example.org
  470. rr_a_;
  471. RRsetPtr rr_cname_; // CNAME in example.org (RDATA will be added)
  472. RRsetPtr rr_cname_a_; // for mixed CNAME + A case
  473. RRsetPtr rr_dname_; // DNAME in example.org (RDATA will be added)
  474. RRsetPtr rr_dname_a_; // for mixed DNAME + A case
  475. RRsetPtr rr_dname_ns_; // for mixed DNAME + NS case
  476. RRsetPtr rr_dname_apex_; // for mixed DNAME + NS case in the apex
  477. RRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
  478. RRsetPtr rr_child_ds_; // DS of a child domain (for delegation, auth data)
  479. RRsetPtr rr_child_glue_; // glue RR of the child domain
  480. RRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
  481. RRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
  482. RRsetPtr rr_child_dname_; // A DNAME under NS
  483. RRsetPtr rr_wild_; // Wildcard record
  484. RRsetPtr rr_cnamewild_; // CNAME at a wildcard
  485. RRsetPtr rr_emptywild_;
  486. RRsetPtr rr_nested_emptywild_;
  487. RRsetPtr rr_nswild_, rr_dnamewild_;
  488. RRsetPtr rr_child_wild_;
  489. RRsetPtr rr_under_wild_;
  490. RRsetPtr rr_not_wild_;
  491. RRsetPtr rr_not_wild_another_;
  492. RRsetPtr rr_nsec3_;
  493. RRsetPtr rr_nsec_;
  494. RRsetPtr rr_ent_nsec2_;
  495. RRsetPtr rr_ent_nsec3_;
  496. RRsetPtr rr_ent_nsec4_;
  497. RRsetPtr rr_ns_nsec_;
  498. RRsetPtr rr_wild_nsec_;
  499. // A faked NSEC3 hash calculator for convenience.
  500. // Tests that need to use the faked hashed values should call
  501. // setNSEC3HashCreator() with a pointer to this variable at the beginning
  502. // of the test (at least before adding any NSEC3/NSEC3PARAM RR).
  503. TestNSEC3HashCreator nsec3_hash_creator_;
  504. /**
  505. * \brief Test one find query to the zone finder.
  506. *
  507. * Asks a query to the zone finder and checks it does not throw and returns
  508. * expected results. It returns nothing, it just signals failures
  509. * to GTEST.
  510. *
  511. * \param name The name to ask for.
  512. * \param rrtype The RRType to ask of.
  513. * \param result The expected code of the result.
  514. * \param check_answer Should a check against equality of the answer be
  515. * done?
  516. * \param answer The expected rrset, if any should be returned.
  517. * \param expected_flags The expected result flags returned via find().
  518. * These can be tested using isWildcard() etc.
  519. * \param zone_finder Check different InMemoryZoneFinder object than
  520. * zone_finder_ (if NULL, uses zone_finder_)
  521. * \param check_wild_answer Checks that the answer has the same RRs, type
  522. * class and TTL as the eqxpected answer and that the name corresponds
  523. * to the one searched. It is meant for checking answers for wildcard
  524. * queries.
  525. */
  526. void findTest(const Name& name, const RRType& rrtype,
  527. ZoneFinder::Result result,
  528. bool check_answer = true,
  529. const ConstRRsetPtr& answer = ConstRRsetPtr(),
  530. ZoneFinder::FindResultFlags expected_flags =
  531. ZoneFinder::RESULT_DEFAULT,
  532. InMemoryZoneFinder* zone_finder = NULL,
  533. ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT,
  534. bool check_wild_answer = false)
  535. {
  536. SCOPED_TRACE("findTest for " + name.toText() + "/" + rrtype.toText());
  537. if (zone_finder == NULL) {
  538. zone_finder = &zone_finder_;
  539. }
  540. const ConstRRsetPtr answer_sig = answer ? answer->getRRsig() :
  541. RRsetPtr(); // note we use the same type as of retval of getRRsig()
  542. // The whole block is inside, because we need to check the result and
  543. // we can't assign to FindResult
  544. EXPECT_NO_THROW({
  545. ZoneFinderContextPtr find_result(zone_finder->find(
  546. name, rrtype, options));
  547. // Check it returns correct answers
  548. EXPECT_EQ(result, find_result->code);
  549. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
  550. find_result->isWildcard());
  551. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
  552. != 0, find_result->isNSECSigned());
  553. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
  554. != 0, find_result->isNSEC3Signed());
  555. if (check_answer) {
  556. if (!answer) {
  557. ASSERT_FALSE(find_result->rrset);
  558. } else {
  559. ASSERT_TRUE(find_result->rrset);
  560. rrsetCheck(answer, find_result->rrset);
  561. if (answer_sig) {
  562. ASSERT_TRUE(find_result->rrset->getRRsig());
  563. rrsetCheck(answer_sig,
  564. find_result->rrset->getRRsig());
  565. }
  566. }
  567. } else if (check_wild_answer) {
  568. ASSERT_NE(ConstRRsetPtr(), answer) <<
  569. "Wrong test, don't check for wild names if you expect "
  570. "empty answer";
  571. ASSERT_NE(ConstRRsetPtr(), find_result->rrset) <<
  572. "No answer found";
  573. // Build the expected answer using the given name and
  574. // other parameter of the base wildcard RRset.
  575. RRsetPtr wildanswer(new RRset(name, answer->getClass(),
  576. answer->getType(),
  577. answer->getTTL()));
  578. RdataIteratorPtr expectedIt(answer->getRdataIterator());
  579. for (; !expectedIt->isLast(); expectedIt->next()) {
  580. wildanswer->addRdata(expectedIt->getCurrent());
  581. }
  582. rrsetCheck(wildanswer, find_result->rrset);
  583. // Same for the RRSIG, if any.
  584. if (answer_sig) {
  585. ASSERT_TRUE(find_result->rrset->getRRsig());
  586. RRsetPtr wildsig(new RRset(name,
  587. answer_sig->getClass(),
  588. RRType::RRSIG(),
  589. answer_sig->getTTL()));
  590. RdataIteratorPtr expectedIt(
  591. answer_sig->getRdataIterator());
  592. for (; !expectedIt->isLast(); expectedIt->next()) {
  593. wildsig->addRdata(expectedIt->getCurrent());
  594. }
  595. rrsetCheck(wildsig, find_result->rrset->getRRsig());
  596. }
  597. }
  598. });
  599. }
  600. /**
  601. * \brief Calls the findAll on the finder and checks the result.
  602. */
  603. void findAllTest(const Name& name, ZoneFinder::Result result,
  604. const vector<ConstRRsetPtr>& expected_rrsets,
  605. ZoneFinder::FindResultFlags expected_flags =
  606. ZoneFinder::RESULT_DEFAULT,
  607. InMemoryZoneFinder* finder = NULL,
  608. const ConstRRsetPtr &rrset_result = ConstRRsetPtr(),
  609. ZoneFinder::FindOptions options =
  610. ZoneFinder::FIND_DEFAULT)
  611. {
  612. if (finder == NULL) {
  613. finder = &zone_finder_;
  614. }
  615. std::vector<ConstRRsetPtr> target;
  616. ZoneFinderContextPtr find_result(finder->findAll(name, target,
  617. options));
  618. EXPECT_EQ(result, find_result->code);
  619. if (!rrset_result) {
  620. EXPECT_FALSE(find_result->rrset);
  621. } else {
  622. ASSERT_TRUE(find_result->rrset);
  623. rrsetCheck(rrset_result, find_result->rrset);
  624. }
  625. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
  626. find_result->isWildcard());
  627. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
  628. != 0, find_result->isNSECSigned());
  629. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
  630. != 0, find_result->isNSEC3Signed());
  631. rrsetsCheck(expected_rrsets.begin(), expected_rrsets.end(),
  632. target.begin(), target.end());
  633. }
  634. };
  635. /**
  636. * \brief Test InMemoryZoneFinder::InMemoryZoneFinder constructor.
  637. *
  638. * Takes the created zone finder and checks its properties they are the same
  639. * as passed parameters.
  640. */
  641. TEST_F(InMemoryZoneFinderTest, constructor) {
  642. ASSERT_EQ(class_, zone_finder_.getClass());
  643. ASSERT_EQ(origin_, zone_finder_.getOrigin());
  644. }
  645. /**
  646. * \brief Test adding.
  647. *
  648. * We test that it throws at the correct moments and the correct exceptions.
  649. * And we test the return value.
  650. */
  651. TEST_F(InMemoryZoneFinderTest, add) {
  652. // This one does not belong to this zone
  653. EXPECT_THROW(zone_finder_.add(rr_out_), OutOfZone);
  654. // Test null pointer
  655. EXPECT_THROW(zone_finder_.add(ConstRRsetPtr()),
  656. InMemoryZoneFinder::NullRRset);
  657. // Now put all the data we have there. It should throw nothing
  658. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  659. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
  660. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
  661. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  662. // Try putting there something twice, it should be rejected
  663. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_)));
  664. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_a_)));
  665. }
  666. TEST_F(InMemoryZoneFinderTest, addMultipleCNAMEs) {
  667. rr_cname_->addRdata(generic::CNAME("canonical2.example.org."));
  668. EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
  669. }
  670. TEST_F(InMemoryZoneFinderTest, addCNAMEThenOther) {
  671. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  672. EXPECT_THROW(zone_finder_.add(rr_cname_a_), InMemoryZoneFinder::AddError);
  673. }
  674. TEST_F(InMemoryZoneFinderTest, addOtherThenCNAME) {
  675. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_a_));
  676. EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
  677. }
  678. TEST_F(InMemoryZoneFinderTest, addCNAMEAndDNSSECRecords) {
  679. // CNAME and RRSIG can coexist
  680. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  681. EXPECT_EQ(SUCCESS, zone_finder_.add(
  682. textToRRset("cname.example.org. 300 IN RRSIG CNAME 5 3 "
  683. "3600 20000101000000 20000201000000 12345 "
  684. "example.org. FAKEFAKEFAKE")));
  685. // Same for NSEC
  686. EXPECT_EQ(SUCCESS, zone_finder_.add(
  687. textToRRset("cname.example.org. 300 IN NSEC "
  688. "dname.example.org. CNAME RRSIG NSEC")));
  689. // Same as above, but adding NSEC first.
  690. EXPECT_EQ(SUCCESS, zone_finder_.add(
  691. textToRRset("cname2.example.org. 300 IN NSEC "
  692. "dname.example.org. CNAME RRSIG NSEC")));
  693. EXPECT_EQ(SUCCESS, zone_finder_.add(
  694. textToRRset("cname2.example.org. 300 IN CNAME c.example.")));
  695. // If there's another type of RRset with NSEC, it should still fail.
  696. EXPECT_EQ(SUCCESS, zone_finder_.add(
  697. textToRRset("cname3.example.org. 300 IN A 192.0.2.1")));
  698. EXPECT_EQ(SUCCESS, zone_finder_.add(
  699. textToRRset("cname3.example.org. 300 IN NSEC "
  700. "dname.example.org. CNAME RRSIG NSEC")));
  701. EXPECT_THROW(zone_finder_.add(textToRRset("cname3.example.org. 300 "
  702. "IN CNAME c.example.")),
  703. InMemoryZoneFinder::AddError);
  704. }
  705. TEST_F(InMemoryZoneFinderTest, findCNAME) {
  706. // install CNAME RR
  707. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  708. // Find A RR of the same. Should match the CNAME
  709. findTest(rr_cname_->getName(), RRType::NS(), ZoneFinder::CNAME, true,
  710. rr_cname_);
  711. // Find the CNAME itself. Should result in normal SUCCESS
  712. findTest(rr_cname_->getName(), RRType::CNAME(), ZoneFinder::SUCCESS, true,
  713. rr_cname_);
  714. }
  715. TEST_F(InMemoryZoneFinderTest, findCNAMEUnderZoneCut) {
  716. // There's nothing special when we find a CNAME under a zone cut
  717. // (with FIND_GLUE_OK). The behavior is different from BIND 9,
  718. // so we test this case explicitly.
  719. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  720. ConstRRsetPtr rr_cname_under_cut_ = textToRRset(
  721. "cname.child.example.org. 300 IN CNAME target.child.example.org.");
  722. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_under_cut_));
  723. findTest(Name("cname.child.example.org"), RRType::AAAA(),
  724. ZoneFinder::CNAME, true, rr_cname_under_cut_,
  725. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  726. }
  727. // Two DNAMEs at single domain are disallowed by RFC 2672, section 3)
  728. // Having a CNAME there is disallowed too, but it is tested by
  729. // addOtherThenCNAME and addCNAMEThenOther.
  730. TEST_F(InMemoryZoneFinderTest, addMultipleDNAMEs) {
  731. rr_dname_->addRdata(generic::DNAME("target2.example.org."));
  732. EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
  733. }
  734. /*
  735. * These two tests ensure that we can't have DNAME and NS at the same
  736. * node with the exception of the apex of zone (forbidden by RFC 2672)
  737. */
  738. TEST_F(InMemoryZoneFinderTest, addDNAMEThenNS) {
  739. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  740. EXPECT_THROW(zone_finder_.add(rr_dname_ns_), InMemoryZoneFinder::AddError);
  741. }
  742. TEST_F(InMemoryZoneFinderTest, addNSThenDNAME) {
  743. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_ns_)));
  744. EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
  745. }
  746. // It is allowed to have NS and DNAME at apex
  747. TEST_F(InMemoryZoneFinderTest, DNAMEAndNSAtApex) {
  748. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
  749. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  750. // The NS should be possible to be found, below should be DNAME, not
  751. // delegation
  752. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  753. findTest(rr_child_ns_->getName(), RRType::A(), ZoneFinder::DNAME, true,
  754. rr_dname_apex_);
  755. }
  756. TEST_F(InMemoryZoneFinderTest, NSAndDNAMEAtApex) {
  757. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  758. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
  759. }
  760. // TODO: Test (and implement) adding data under DNAME. That is forbidden by
  761. // 2672 as well.
  762. // Search under a DNAME record. It should return the DNAME
  763. TEST_F(InMemoryZoneFinderTest, findBelowDNAME) {
  764. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  765. findTest(Name("below.dname.example.org"), RRType::A(), ZoneFinder::DNAME,
  766. true, rr_dname_);
  767. }
  768. // Search at the domain with DNAME. It should act as DNAME isn't there, DNAME
  769. // influences only the data below (see RFC 2672, section 3)
  770. TEST_F(InMemoryZoneFinderTest, findAtDNAME) {
  771. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  772. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_a_)));
  773. const Name dname_name(rr_dname_->getName());
  774. findTest(dname_name, RRType::A(), ZoneFinder::SUCCESS, true, rr_dname_a_);
  775. findTest(dname_name, RRType::DNAME(), ZoneFinder::SUCCESS, true,
  776. rr_dname_);
  777. findTest(dname_name, RRType::TXT(), ZoneFinder::NXRRSET, true);
  778. }
  779. // Try searching something that is both under NS and DNAME, without and with
  780. // GLUE_OK mode (it should stop at the NS and DNAME respectively).
  781. TEST_F(InMemoryZoneFinderTest, DNAMEUnderNS) {
  782. zone_finder_.add(rr_child_ns_);
  783. zone_finder_.add(rr_child_dname_);
  784. Name lowName("below.dname.child.example.org.");
  785. findTest(lowName, RRType::A(), ZoneFinder::DELEGATION, true, rr_child_ns_);
  786. findTest(lowName, RRType::A(), ZoneFinder::DNAME, true, rr_child_dname_,
  787. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  788. }
  789. // Test adding child zones and zone cut handling
  790. TEST_F(InMemoryZoneFinderTest, delegationNS) {
  791. // add in-zone data
  792. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  793. // install a zone cut
  794. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  795. // below the zone cut
  796. findTest(Name("www.child.example.org"), RRType::A(),
  797. ZoneFinder::DELEGATION, true, rr_child_ns_);
  798. // at the zone cut
  799. findTest(Name("child.example.org"), RRType::A(), ZoneFinder::DELEGATION,
  800. true, rr_child_ns_);
  801. findTest(Name("child.example.org"), RRType::NS(), ZoneFinder::DELEGATION,
  802. true, rr_child_ns_);
  803. // finding NS for the apex (origin) node. This must not be confused
  804. // with delegation due to the existence of an NS RR.
  805. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  806. // unusual case of "nested delegation": the highest cut should be used.
  807. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
  808. findTest(Name("www.grand.child.example.org"), RRType::A(),
  809. // note: !rr_grandchild_ns_
  810. ZoneFinder::DELEGATION, true, rr_child_ns_);
  811. }
  812. TEST_F(InMemoryZoneFinderTest, delegationWithDS) {
  813. // Similar setup to the previous one, but with DS RR at the delegation
  814. // point.
  815. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_));
  816. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  817. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ds_));
  818. // Normal types of query should result in delegation, but DS query
  819. // should be considered in-zone (but only exactly at the delegation point).
  820. findTest(Name("child.example.org"), RRType::A(), ZoneFinder::DELEGATION,
  821. true, rr_child_ns_);
  822. findTest(Name("child.example.org"), RRType::DS(), ZoneFinder::SUCCESS,
  823. true, rr_child_ds_);
  824. findTest(Name("grand.child.example.org"), RRType::DS(),
  825. ZoneFinder::DELEGATION, true, rr_child_ns_);
  826. // There's nothing special for DS query at the zone apex. It would
  827. // normally result in NXRRSET.
  828. findTest(Name("example.org"), RRType::DS(), ZoneFinder::NXRRSET,
  829. true, ConstRRsetPtr());
  830. }
  831. TEST_F(InMemoryZoneFinderTest, findAny) {
  832. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  833. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  834. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
  835. vector<ConstRRsetPtr> expected_sets;
  836. // origin
  837. expected_sets.push_back(rr_a_);
  838. expected_sets.push_back(rr_ns_);
  839. findAllTest(origin_, ZoneFinder::SUCCESS, expected_sets);
  840. // out zone name
  841. EXPECT_THROW(findAllTest(Name("example.com"), ZoneFinder::NXDOMAIN,
  842. vector<ConstRRsetPtr>()),
  843. OutOfZone);
  844. expected_sets.clear();
  845. expected_sets.push_back(rr_child_glue_);
  846. findAllTest(rr_child_glue_->getName(), ZoneFinder::SUCCESS, expected_sets);
  847. // add zone cut
  848. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  849. // zone cut
  850. findAllTest(rr_child_ns_->getName(), ZoneFinder::DELEGATION,
  851. vector<ConstRRsetPtr>(), ZoneFinder::RESULT_DEFAULT,
  852. NULL, rr_child_ns_);
  853. // glue for this zone cut
  854. findAllTest(rr_child_glue_->getName(),ZoneFinder::DELEGATION,
  855. vector<ConstRRsetPtr>(), ZoneFinder::RESULT_DEFAULT,
  856. NULL, rr_child_ns_);
  857. }
  858. TEST_F(InMemoryZoneFinderTest, glue) {
  859. // install zone data:
  860. // a zone cut
  861. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  862. // glue for this cut
  863. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
  864. // a nested zone cut (unusual)
  865. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
  866. // glue under the deeper zone cut
  867. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_glue_)));
  868. // by default glue is hidden due to the zone cut
  869. findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
  870. true, rr_child_ns_);
  871. // If we do it in the "glue OK" mode, we should find the exact match.
  872. findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
  873. rr_child_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
  874. ZoneFinder::FIND_GLUE_OK);
  875. // glue OK + NXRRSET case
  876. findTest(rr_child_glue_->getName(), RRType::AAAA(), ZoneFinder::NXRRSET,
  877. true, ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, NULL,
  878. ZoneFinder::FIND_GLUE_OK);
  879. // glue OK + NXDOMAIN case
  880. findTest(Name("www.child.example.org"), RRType::A(),
  881. ZoneFinder::DELEGATION, true, rr_child_ns_,
  882. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  883. // nested cut case. The glue should be found.
  884. findTest(rr_grandchild_glue_->getName(), RRType::AAAA(),
  885. ZoneFinder::SUCCESS,
  886. true, rr_grandchild_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
  887. ZoneFinder::FIND_GLUE_OK);
  888. // A non-existent name in nested cut. This should result in delegation
  889. // at the highest zone cut.
  890. findTest(Name("www.grand.child.example.org"), RRType::TXT(),
  891. ZoneFinder::DELEGATION, true, rr_child_ns_,
  892. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  893. }
  894. /**
  895. * \brief Test searching.
  896. *
  897. * Check it finds or does not find correctly and does not throw exceptions.
  898. * \todo This doesn't do any kind of CNAME and so on. If it isn't
  899. * directly there, it just tells it doesn't exist.
  900. */
  901. void
  902. InMemoryZoneFinderTest::findCheck(ZoneFinder::FindResultFlags expected_flags,
  903. ZoneFinder::FindOptions find_options)
  904. {
  905. // Fill some data inside
  906. // Now put all the data we have there. It should throw nothing
  907. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  908. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
  909. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
  910. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  911. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  912. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  913. }
  914. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  915. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  916. }
  917. // These two should be successful
  918. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  919. findTest(rr_ns_a_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
  920. rr_ns_a_);
  921. // These domains don't exist. (and one is out of the zone). In an
  922. // NSEC-signed zone with DNSSEC records requested, it should return the
  923. // covering NSEC for the query name (the actual NSEC in the test data may
  924. // not really "cover" it, but for the purpose of this test it's okay).
  925. ConstRRsetPtr expected_nsec; // by default it's NULL
  926. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
  927. (find_options & ZoneFinder::FIND_DNSSEC) != 0) {
  928. expected_nsec = rr_nsec_;
  929. }
  930. // There's no other name between this one and the origin, so when NSEC
  931. // is to be returned it should be the origin NSEC.
  932. findTest(Name("nothere.example.org"), RRType::A(),
  933. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  934. NULL, find_options);
  935. // The previous name in the zone is "ns.example.org", but it doesn't
  936. // have an NSEC. It should be skipped and the origin NSEC will be
  937. // returned as the "closest NSEC".
  938. findTest(Name("nxdomain.example.org"), RRType::A(),
  939. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  940. NULL, find_options);
  941. EXPECT_THROW(zone_finder_.find(Name("example.net"), RRType::A()),
  942. OutOfZone);
  943. // These domain exist but don't have the provided RRType. For the latter
  944. // one we now add its NSEC (which was delayed so that it wouldn't break
  945. // other cases above).
  946. findTest(origin_, RRType::AAAA(), ZoneFinder::NXRRSET, true,
  947. expected_nsec, expected_flags, NULL, find_options);
  948. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  949. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_nsec_));
  950. if ((find_options & ZoneFinder::FIND_DNSSEC) != 0) {
  951. expected_nsec = rr_ns_nsec_;
  952. }
  953. }
  954. findTest(rr_ns_a_->getName(), RRType::NS(), ZoneFinder::NXRRSET, true,
  955. expected_nsec, expected_flags, NULL, find_options);
  956. }
  957. TEST_F(InMemoryZoneFinderTest, find) {
  958. findCheck();
  959. }
  960. TEST_F(InMemoryZoneFinderTest, findNSEC3Signed) {
  961. findCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  962. }
  963. TEST_F(InMemoryZoneFinderTest, findNSEC3SignedWithDNSSEC) {
  964. // For NSEC3-signed zones, specifying the DNSSEC option shouldn't change
  965. // anything (the NSEC3_SIGNED flag is always set, and no records are
  966. // returned for negative cases regardless).
  967. findCheck(ZoneFinder::RESULT_NSEC3_SIGNED, ZoneFinder::FIND_DNSSEC);
  968. }
  969. TEST_F(InMemoryZoneFinderTest, findNSECSigned) {
  970. // NSEC-signed zone, without requesting DNSSEC (no NSEC should be provided)
  971. findCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  972. }
  973. // Generalized test for Empty Nonterminal (ENT) cases with NSEC
  974. void
  975. InMemoryZoneFinderTest::findNSECENTCheck(const Name& ent_name,
  976. ConstRRsetPtr expected_nsec,
  977. ZoneFinder::FindResultFlags expected_flags)
  978. {
  979. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_emptywild_));
  980. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_under_wild_));
  981. // Sanity check: Should result in NXRRSET
  982. findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
  983. ConstRRsetPtr(), expected_flags);
  984. // Sanity check: No NSEC added yet
  985. findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
  986. ConstRRsetPtr(), expected_flags,
  987. NULL, ZoneFinder::FIND_DNSSEC);
  988. // Now add the NSEC rrs making it a 'complete' zone (in terms of NSEC,
  989. // there are no sigs)
  990. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  991. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ent_nsec2_));
  992. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ent_nsec3_));
  993. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ent_nsec4_));
  994. // Should result in NXRRSET, and RESULT_NSEC_SIGNED
  995. findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
  996. ConstRRsetPtr(),
  997. expected_flags | ZoneFinder::RESULT_NSEC_SIGNED);
  998. // And check for the NSEC if DNSSEC_OK
  999. findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
  1000. expected_nsec, expected_flags | ZoneFinder::RESULT_NSEC_SIGNED,
  1001. NULL, ZoneFinder::FIND_DNSSEC);
  1002. }
  1003. TEST_F(InMemoryZoneFinderTest,findNSECEmptyNonterminal) {
  1004. // Non-wildcard case
  1005. findNSECENTCheck(Name("wild.example.org"), rr_ent_nsec3_);
  1006. }
  1007. TEST_F(InMemoryZoneFinderTest,findNSECEmptyNonterminalWildcard) {
  1008. // Wildcard case, above actual wildcard
  1009. findNSECENTCheck(Name("foo.example.org"), rr_nsec_);
  1010. }
  1011. TEST_F(InMemoryZoneFinderTest,findNSECEmptyNonterminalAtWildcard) {
  1012. // Wildcard case, at actual wildcard
  1013. findNSECENTCheck(Name("bar.foo.example.org"), rr_nsec_,
  1014. ZoneFinder::RESULT_WILDCARD);
  1015. }
  1016. TEST_F(InMemoryZoneFinderTest, findNSECSignedWithDNSSEC) {
  1017. // NSEC-signed zone, requesting DNSSEC (NSEC should be provided)
  1018. findCheck(ZoneFinder::RESULT_NSEC_SIGNED, ZoneFinder::FIND_DNSSEC);
  1019. }
  1020. void
  1021. InMemoryZoneFinderTest::emptyNodeCheck(
  1022. ZoneFinder::FindResultFlags expected_flags)
  1023. {
  1024. /*
  1025. * The backend RBTree for this test should look like as follows:
  1026. * example.org
  1027. * |
  1028. * baz (empty; easy case)
  1029. * / | \
  1030. * bar | x.foo ('foo' part is empty; a bit trickier)
  1031. * bbb
  1032. * /
  1033. * aaa
  1034. */
  1035. // Construct the test zone
  1036. const char* const names[] = {
  1037. "bar.example.org.", "x.foo.example.org.", "aaa.baz.example.org.",
  1038. "bbb.baz.example.org.", NULL};
  1039. for (int i = 0; names[i] != NULL; ++i) {
  1040. ConstRRsetPtr rrset = textToRRset(string(names[i]) +
  1041. " 300 IN A 192.0.2.1");
  1042. EXPECT_EQ(SUCCESS, zone_finder_.add(rrset));
  1043. }
  1044. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1045. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1046. }
  1047. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1048. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1049. }
  1050. // empty node matching, easy case: the node for 'baz' exists with
  1051. // no data.
  1052. findTest(Name("baz.example.org"), RRType::A(), ZoneFinder::NXRRSET, true,
  1053. ConstRRsetPtr(), expected_flags);
  1054. // empty node matching, a trickier case: the node for 'foo' is part of
  1055. // "x.foo", which should be considered an empty node.
  1056. findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET, true,
  1057. ConstRRsetPtr(), expected_flags);
  1058. // "org" is contained in "example.org", but it shouldn't be treated as
  1059. // NXRRSET because it's out of zone.
  1060. // Note: basically we don't expect such a query to be performed (the common
  1061. // operation is to identify the best matching zone first then perform
  1062. // search it), but we shouldn't be confused even in the unexpected case.
  1063. EXPECT_THROW(zone_finder_.find(Name("org"), RRType::A()), OutOfZone);
  1064. }
  1065. TEST_F(InMemoryZoneFinderTest, emptyNode) {
  1066. emptyNodeCheck();
  1067. }
  1068. TEST_F(InMemoryZoneFinderTest, emptyNodeNSEC3) {
  1069. emptyNodeCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1070. }
  1071. TEST_F(InMemoryZoneFinderTest, emptyNodeNSEC) {
  1072. emptyNodeCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1073. }
  1074. TEST_F(InMemoryZoneFinderTest, load) {
  1075. // Put some data inside the zone
  1076. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, zone_finder_.add(rr_ns_)));
  1077. // Loading with different origin should fail
  1078. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
  1079. MasterLoadError);
  1080. // See the original data is still there, survived the exception
  1081. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  1082. // Create correct zone
  1083. InMemoryZoneFinder rootzone(class_, Name("."));
  1084. // Try putting something inside
  1085. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, rootzone.add(rr_ns_aaaa_)));
  1086. // Load the zone. It should overwrite/remove the above RRset
  1087. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  1088. // Now see there are some rrsets (we don't look inside, though)
  1089. findTest(Name("."), RRType::SOA(), ZoneFinder::SUCCESS, false,
  1090. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1091. findTest(Name("."), RRType::NS(), ZoneFinder::SUCCESS, false,
  1092. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1093. findTest(Name("a.root-servers.net."), RRType::A(), ZoneFinder::SUCCESS,
  1094. false, ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1095. // But this should no longer be here
  1096. findTest(rr_ns_a_->getName(), RRType::AAAA(), ZoneFinder::NXDOMAIN, true,
  1097. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1098. // Try loading zone that is wrong in a different way
  1099. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  1100. MasterLoadError);
  1101. }
  1102. TEST_F(InMemoryZoneFinderTest, loadFromIterator) {
  1103. // The initial test set doesn't have SOA at the apex.
  1104. findTest(origin_, RRType::SOA(), ZoneFinder::NXRRSET, false,
  1105. ConstRRsetPtr());
  1106. // The content of the new version of zone to be first installed to
  1107. // the SQLite3 data source, then to in-memory via SQLite3. The data are
  1108. // chosen to cover major check points of the implementation:
  1109. // - the previously non-existent record is added (SOA)
  1110. // - An RRSIG is given from the iterator before the RRset it covers
  1111. // (RRSIG for SOA, because they are sorted by name then rrtype as text)
  1112. // - An RRset containing multiple RRs (ns1/A)
  1113. // - RRSIGs for different owner names
  1114. stringstream ss;
  1115. const char* const soa_txt = "example.org. 300 IN SOA . . 0 0 0 0 0\n";
  1116. const char* const soa_sig_txt = "example.org. 300 IN RRSIG SOA 5 3 300 "
  1117. "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
  1118. const char* const a_txt =
  1119. "ns1.example.org. 300 IN A 192.0.2.1\n"
  1120. "ns1.example.org. 300 IN A 192.0.2.2\n";
  1121. const char* const a_sig_txt = "ns1.example.org. 300 IN RRSIG A 5 3 300 "
  1122. "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
  1123. ss << soa_txt << soa_sig_txt << a_txt << a_sig_txt;
  1124. shared_ptr<DataSourceClient> db_client = unittest::createSQLite3Client(
  1125. class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied", ss);
  1126. zone_finder_.load(*db_client->getIterator(origin_));
  1127. // The new content should be visible, including the previously-nonexistent
  1128. // SOA.
  1129. RRsetPtr expected_answer = textToRRset(soa_txt, RRClass::IN(), origin_);
  1130. expected_answer->addRRsig(textToRRset(soa_sig_txt));
  1131. findTest(origin_, RRType::SOA(), ZoneFinder::SUCCESS, true,
  1132. expected_answer, ZoneFinder::RESULT_DEFAULT, NULL,
  1133. ZoneFinder::FIND_DNSSEC);
  1134. expected_answer = textToRRset(a_txt);
  1135. expected_answer->addRRsig(textToRRset(a_sig_txt));
  1136. findTest(Name("ns1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
  1137. expected_answer, ZoneFinder::RESULT_DEFAULT, NULL,
  1138. ZoneFinder::FIND_DNSSEC);
  1139. // File name should be (re)set to empty.
  1140. EXPECT_TRUE(zone_finder_.getFileName().empty());
  1141. // Loading the zone with an iterator separating RRs of the same RRset
  1142. // will fail because the resulting sequence doesn't meet assumptions of
  1143. // the (current) in-memory implementation.
  1144. EXPECT_THROW(zone_finder_.load(*db_client->getIterator(origin_, true)),
  1145. MasterLoadError);
  1146. // Load the zone from a file that contains more realistic data (borrowed
  1147. // from a different test). There's nothing special in this case for the
  1148. // purpose of this test, so it should just succeed.
  1149. db_client = unittest::createSQLite3Client(
  1150. class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied",
  1151. TEST_DATA_DIR "/contexttest.zone");
  1152. zone_finder_.load(*db_client->getIterator(origin_));
  1153. // just checking a couple of RRs in the new version of zone.
  1154. findTest(Name("mx1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
  1155. textToRRset("mx1.example.org. 3600 IN A 192.0.2.10"));
  1156. findTest(Name("ns1.example.org"), RRType::AAAA(), ZoneFinder::SUCCESS,
  1157. true, textToRRset("ns1.example.org. 3600 IN AAAA 2001:db8::1"));
  1158. }
  1159. /*
  1160. * Test that puts a (simple) wildcard into the zone and checks we can
  1161. * correctly find the data.
  1162. */
  1163. void
  1164. InMemoryZoneFinderTest::wildcardCheck(
  1165. ZoneFinder::FindResultFlags expected_flags,
  1166. ZoneFinder::FindOptions find_options)
  1167. {
  1168. /*
  1169. * example.org.
  1170. * |
  1171. * [cname]wild (not *.wild, should have wild mark)
  1172. * |
  1173. * *
  1174. */
  1175. // If the zone is "signed" (detecting it by the NSEC/NSEC3 signed flags),
  1176. // add RRSIGs to the records.
  1177. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 ||
  1178. (expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1179. // Convenience shortcut. The RDATA is not really validatable, but
  1180. // it doesn't matter for our tests.
  1181. const char* const rrsig_common = "5 3 3600 "
  1182. "20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE";
  1183. find_options = find_options | ZoneFinder::FIND_DNSSEC;
  1184. rr_wild_->addRRsig(textToRRset("*.wild.example.org. 300 IN RRSIG A " +
  1185. string(rrsig_common)));
  1186. rr_cnamewild_->addRRsig(textToRRset("*.cnamewild.example.org. 300 IN "
  1187. "RRSIG CNAME " +
  1188. string(rrsig_common)));
  1189. }
  1190. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1191. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cnamewild_));
  1192. // If the zone is expected to be "signed" with NSEC3, add an NSEC3.
  1193. // (the content of the NSEC3 shouldn't matter)
  1194. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1195. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1196. }
  1197. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1198. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1199. }
  1200. // Search at the parent. The parent will not have the A, but it will
  1201. // be in the wildcard (so check the wildcard isn't matched at the parent)
  1202. {
  1203. SCOPED_TRACE("Search at parent");
  1204. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1205. findTest(Name("wild.example.org"), RRType::A(),
  1206. ZoneFinder::NXRRSET, true, rr_nsec_, expected_flags,
  1207. NULL, find_options);
  1208. } else {
  1209. findTest(Name("wild.example.org"), RRType::A(),
  1210. ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
  1211. expected_flags, NULL, find_options);
  1212. }
  1213. }
  1214. // For the test setup of "NSEC-signed" zone, we might expect it will
  1215. // be returned with a negative result, either because wildcard match is
  1216. // disabled by the search option or because wildcard match is canceled
  1217. // per protocol.
  1218. ConstRRsetPtr expected_nsec; // by default it's NULL
  1219. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
  1220. (find_options & ZoneFinder::FIND_DNSSEC) != 0) {
  1221. expected_nsec = rr_nsec_;
  1222. }
  1223. // Explicitly converting the following to const pointers; some compilers
  1224. // would complain about mixed use of const and non const in ?: below.
  1225. const ConstRRsetPtr rr_wild = rr_wild_;
  1226. const ConstRRsetPtr rr_cnamewild = rr_cnamewild_;
  1227. // Search the original name of wildcard
  1228. {
  1229. SCOPED_TRACE("Search directly at *");
  1230. findTest(Name("*.wild.example.org"), RRType::A(), ZoneFinder::SUCCESS,
  1231. true, rr_wild_, ZoneFinder::RESULT_DEFAULT, NULL,
  1232. find_options);
  1233. }
  1234. // Below some of the test cases will normally result in a wildcard match;
  1235. // if NO_WILDCARD is specified, it should result in NXDOMAIN instead,
  1236. // and, when available and requested, the covering NSEC will be returned.
  1237. // The following are shortcut parameters to unify these cases.
  1238. const bool wild_ok = ((find_options & ZoneFinder::NO_WILDCARD) == 0);
  1239. const ZoneFinder::FindResultFlags wild_expected_flags =
  1240. wild_ok ? (ZoneFinder::RESULT_WILDCARD | expected_flags) :
  1241. expected_flags;
  1242. // Search "created" name.
  1243. {
  1244. SCOPED_TRACE("Search at created child");
  1245. findTest(Name("a.wild.example.org"), RRType::A(),
  1246. wild_ok ? ZoneFinder::SUCCESS : ZoneFinder::NXDOMAIN, false,
  1247. wild_ok ? rr_wild : expected_nsec,
  1248. wild_expected_flags, NULL, find_options, wild_ok);
  1249. }
  1250. // Search name that has CNAME.
  1251. {
  1252. SCOPED_TRACE("Matching CNAME");
  1253. findTest(Name("a.cnamewild.example.org"), RRType::A(),
  1254. wild_ok ? ZoneFinder::CNAME : ZoneFinder::NXDOMAIN, false,
  1255. wild_ok ? rr_cnamewild : expected_nsec,
  1256. wild_expected_flags, NULL, find_options, wild_ok);
  1257. }
  1258. // Search another created name, this time little bit lower
  1259. {
  1260. SCOPED_TRACE("Search at created grand-child");
  1261. findTest(Name("a.b.wild.example.org"), RRType::A(),
  1262. wild_ok ? ZoneFinder::SUCCESS : ZoneFinder::NXDOMAIN, false,
  1263. wild_ok ? rr_wild : expected_nsec,
  1264. wild_expected_flags, NULL, find_options, wild_ok);
  1265. }
  1266. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_under_wild_));
  1267. {
  1268. SCOPED_TRACE("Search under non-wildcard");
  1269. findTest(Name("bar.foo.wild.example.org"), RRType::A(),
  1270. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  1271. NULL, find_options);
  1272. }
  1273. // Wildcard match, but no data. We add the additional NSEC at the wildcard
  1274. // at this point so that it wouldn't break other tests above. Note also
  1275. // that in the NO_WILDCARD case the resulting NSEC is the same. Ideally
  1276. // we could use a more tricky setup so we can distinguish these cases,
  1277. // but for this purpose it's not bad; what we'd like to test here is that
  1278. // wildcard substitution doesn't happen for either case, and the
  1279. // NO_WILDCARD effect itself can be checked by the result code (NXDOMAIN).
  1280. ConstRRsetPtr expected_wild_nsec; // by default it's NULL
  1281. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1282. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_nsec_));
  1283. expected_wild_nsec = rr_wild_nsec_;
  1284. }
  1285. {
  1286. SCOPED_TRACE("Search at wildcard, no data");
  1287. findTest(Name("a.wild.example.org"), RRType::AAAA(),
  1288. wild_ok ? ZoneFinder::NXRRSET : ZoneFinder::NXDOMAIN, true,
  1289. wild_ok ? expected_wild_nsec : expected_wild_nsec,
  1290. wild_expected_flags, NULL, find_options);
  1291. }
  1292. }
  1293. TEST_F(InMemoryZoneFinderTest, wildcard) {
  1294. // Normal case
  1295. wildcardCheck();
  1296. }
  1297. TEST_F(InMemoryZoneFinderTest, wildcardNSEC3) {
  1298. // Similar to the previous one, but the zone signed with NSEC3
  1299. wildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1300. }
  1301. TEST_F(InMemoryZoneFinderTest, wildcardNSEC) {
  1302. // Similar to the previous one, but the zone is signed with NSEC
  1303. wildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1304. }
  1305. TEST_F(InMemoryZoneFinderTest, wildcardDisabledWithNSEC) {
  1306. // Wildcard is disabled. In practice, this is used as part of query
  1307. // processing for an NSEC-signed zone, so we test that case specifically.
  1308. wildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED, ZoneFinder::NO_WILDCARD);
  1309. }
  1310. TEST_F(InMemoryZoneFinderTest, wildcardDisabledWithoutNSEC) {
  1311. // Similar to the previous once, but check the behavior for a non signed
  1312. // zone just in case.
  1313. wildcardCheck(ZoneFinder::RESULT_DEFAULT, ZoneFinder::NO_WILDCARD);
  1314. }
  1315. /*
  1316. * Test that we don't match a wildcard if we get under delegation.
  1317. * By 4.3.3 of RFC1034:
  1318. * "Wildcard RRs do not apply:
  1319. * - When the query is in another zone. That is, delegation cancels
  1320. * the wildcard defaults."
  1321. */
  1322. TEST_F(InMemoryZoneFinderTest, delegatedWildcard) {
  1323. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_wild_));
  1324. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  1325. {
  1326. SCOPED_TRACE("Looking under delegation point");
  1327. findTest(Name("a.child.example.org"), RRType::A(),
  1328. ZoneFinder::DELEGATION, true, rr_child_ns_);
  1329. }
  1330. {
  1331. SCOPED_TRACE("Looking under delegation point in GLUE_OK mode");
  1332. findTest(Name("a.child.example.org"), RRType::A(),
  1333. ZoneFinder::DELEGATION, true, rr_child_ns_,
  1334. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  1335. }
  1336. }
  1337. // Tests combination of wildcard and ANY.
  1338. void
  1339. InMemoryZoneFinderTest::anyWildcardCheck(
  1340. ZoneFinder::FindResultFlags expected_flags)
  1341. {
  1342. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1343. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1344. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1345. }
  1346. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1347. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1348. }
  1349. vector<ConstRRsetPtr> expected_sets;
  1350. // First try directly the name (normal match)
  1351. {
  1352. SCOPED_TRACE("Asking directly for *");
  1353. expected_sets.push_back(rr_wild_);
  1354. findAllTest(Name("*.wild.example.org"), ZoneFinder::SUCCESS,
  1355. expected_sets);
  1356. }
  1357. // Then a wildcard match
  1358. {
  1359. SCOPED_TRACE("Asking in the wild way");
  1360. expected_sets.clear();
  1361. RRsetPtr expected(new RRset(Name("a.wild.example.org"),
  1362. rr_wild_->getClass(), rr_wild_->getType(),
  1363. rr_wild_->getTTL()));
  1364. expected->addRdata(rr_wild_->getRdataIterator()->getCurrent());
  1365. expected_sets.push_back(expected);
  1366. findAllTest(Name("a.wild.example.org"), ZoneFinder::SUCCESS,
  1367. expected_sets,
  1368. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1369. }
  1370. }
  1371. TEST_F(InMemoryZoneFinderTest, anyWildcard) {
  1372. anyWildcardCheck();
  1373. }
  1374. TEST_F(InMemoryZoneFinderTest, anyWildcardNSEC3) {
  1375. anyWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1376. }
  1377. TEST_F(InMemoryZoneFinderTest, anyWildcardNSEC) {
  1378. anyWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1379. }
  1380. // Test there's nothing in the wildcard in the middle if we load
  1381. // wild.*.foo.example.org.
  1382. void
  1383. InMemoryZoneFinderTest::emptyWildcardCheck(
  1384. ZoneFinder::FindResultFlags expected_flags)
  1385. {
  1386. /*
  1387. * example.org.
  1388. * foo
  1389. * *
  1390. * wild
  1391. */
  1392. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_emptywild_));
  1393. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1394. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1395. }
  1396. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1397. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1398. }
  1399. {
  1400. SCOPED_TRACE("Asking for the original record under wildcard");
  1401. findTest(Name("wild.*.foo.example.org"), RRType::A(),
  1402. ZoneFinder::SUCCESS, true, rr_emptywild_);
  1403. }
  1404. {
  1405. SCOPED_TRACE("Asking for A record");
  1406. findTest(Name("a.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
  1407. true, ConstRRsetPtr(),
  1408. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1409. findTest(Name("*.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
  1410. true, ConstRRsetPtr(), expected_flags);
  1411. findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
  1412. true, ConstRRsetPtr(), expected_flags);
  1413. }
  1414. {
  1415. SCOPED_TRACE("Asking for ANY record");
  1416. findAllTest(Name("*.foo.example.org"), ZoneFinder::NXRRSET,
  1417. vector<ConstRRsetPtr>(), expected_flags);
  1418. findAllTest(Name("a.foo.example.org"), ZoneFinder::NXRRSET,
  1419. vector<ConstRRsetPtr>(),
  1420. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1421. }
  1422. {
  1423. SCOPED_TRACE("Asking on the non-terminal");
  1424. findTest(Name("wild.bar.foo.example.org"), RRType::A(),
  1425. ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
  1426. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1427. }
  1428. }
  1429. TEST_F(InMemoryZoneFinderTest, emptyWildcard) {
  1430. emptyWildcardCheck();
  1431. }
  1432. TEST_F(InMemoryZoneFinderTest, emptyWildcardNSEC3) {
  1433. emptyWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1434. }
  1435. TEST_F(InMemoryZoneFinderTest, emptyWildcardNSEC) {
  1436. emptyWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1437. }
  1438. // Same as emptyWildcard, but with multiple * in the path.
  1439. TEST_F(InMemoryZoneFinderTest, nestedEmptyWildcard) {
  1440. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nested_emptywild_));
  1441. {
  1442. SCOPED_TRACE("Asking for the original record under wildcards");
  1443. findTest(Name("wild.*.foo.*.bar.example.org"), RRType::A(),
  1444. ZoneFinder::SUCCESS, true, rr_nested_emptywild_);
  1445. }
  1446. {
  1447. SCOPED_TRACE("Matching wildcard against empty nonterminal");
  1448. const char* names[] = {
  1449. "baz.foo.*.bar.example.org",
  1450. "baz.foo.baz.bar.example.org",
  1451. "*.foo.baz.bar.example.org",
  1452. NULL
  1453. };
  1454. for (const char** name = names; *name != NULL; ++ name) {
  1455. SCOPED_TRACE(string("Node ") + *name);
  1456. findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET, true,
  1457. ConstRRsetPtr(), ZoneFinder::RESULT_WILDCARD);
  1458. }
  1459. }
  1460. // Domains to test
  1461. const char* names[] = {
  1462. "*.foo.*.bar.example.org",
  1463. "foo.*.bar.example.org",
  1464. "*.bar.example.org",
  1465. "bar.example.org",
  1466. NULL
  1467. };
  1468. {
  1469. SCOPED_TRACE("Asking directly for A on parent nodes");
  1470. for (const char** name = names; *name != NULL; ++ name) {
  1471. SCOPED_TRACE(string("Node ") + *name);
  1472. findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET);
  1473. }
  1474. }
  1475. {
  1476. SCOPED_TRACE("Asking for ANY on parent nodes");
  1477. for (const char** name = names; *name != NULL; ++ name) {
  1478. SCOPED_TRACE(string("Node ") + *name);
  1479. findAllTest(Name(*name), ZoneFinder::NXRRSET,
  1480. vector<ConstRRsetPtr>());
  1481. }
  1482. }
  1483. }
  1484. // We run this part twice from the below test, in two slightly different
  1485. // situations
  1486. void
  1487. InMemoryZoneFinderTest::doCancelWildcardCheck(
  1488. ZoneFinder::FindResultFlags expected_flags,
  1489. ZoneFinder::FindOptions find_options)
  1490. {
  1491. // These should be canceled
  1492. {
  1493. SCOPED_TRACE("Canceled under foo.wild.example.org");
  1494. // For an NSEC-signed zone with DNSSEC requested, the covering NSEC
  1495. // should be returned. The expected NSEC is actually just the only
  1496. // NSEC in the test data, but in this context it doesn't matter;
  1497. // it's sufficient just to check any NSEC is returned (or not).
  1498. ConstRRsetPtr expected_nsec; // by default it's NULL
  1499. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
  1500. (find_options & ZoneFinder::FIND_DNSSEC)) {
  1501. expected_nsec = rr_nsec_;
  1502. }
  1503. findTest(Name("aaa.foo.wild.example.org"), RRType::A(),
  1504. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  1505. NULL, find_options);
  1506. findTest(Name("zzz.foo.wild.example.org"), RRType::A(),
  1507. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  1508. NULL, find_options);
  1509. }
  1510. // This is existing, non-wildcard domain, shouldn't wildcard at all
  1511. {
  1512. SCOPED_TRACE("Existing domain under foo.wild.example.org");
  1513. findTest(Name("bar.foo.wild.example.org"), RRType::A(),
  1514. ZoneFinder::SUCCESS, true, rr_not_wild_);
  1515. }
  1516. // These should be caught by the wildcard
  1517. {
  1518. SCOPED_TRACE("Neighbor wildcards to foo.wild.example.org");
  1519. const char* names[] = {
  1520. "aaa.bbb.wild.example.org",
  1521. "aaa.zzz.wild.example.org",
  1522. "zzz.wild.example.org",
  1523. NULL
  1524. };
  1525. for (const char** name = names; *name != NULL; ++ name) {
  1526. SCOPED_TRACE(string("Node ") + *name);
  1527. findTest(Name(*name), RRType::A(), ZoneFinder::SUCCESS, false,
  1528. rr_wild_,
  1529. ZoneFinder::RESULT_WILDCARD | expected_flags, NULL,
  1530. ZoneFinder::FIND_DEFAULT, true);
  1531. }
  1532. }
  1533. // This shouldn't be wildcarded, it's an existing domain
  1534. {
  1535. SCOPED_TRACE("The foo.wild.example.org itself");
  1536. findTest(Name("foo.wild.example.org"), RRType::A(),
  1537. ZoneFinder::NXRRSET, true, ConstRRsetPtr(), expected_flags);
  1538. }
  1539. }
  1540. /*
  1541. * This tests that if there's a name between the wildcard domain and the
  1542. * searched one, it will not trigger wildcard, for example, if we have
  1543. * *.wild.example.org and bar.foo.wild.example.org, then we know
  1544. * foo.wild.example.org exists and is not wildcard. Therefore, search for
  1545. * aaa.foo.wild.example.org should return NXDOMAIN.
  1546. *
  1547. * Tests few cases "around" the canceled wildcard match, to see something that
  1548. * shouldn't be canceled isn't.
  1549. */
  1550. TEST_F(InMemoryZoneFinderTest, cancelWildcard) {
  1551. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1552. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
  1553. {
  1554. SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
  1555. doCancelWildcardCheck();
  1556. }
  1557. // Try putting another one under foo.wild....
  1558. // The result should be the same but it will be done in another way in the
  1559. // code, because the foo.wild.example.org will exist in the tree.
  1560. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
  1561. {
  1562. SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
  1563. doCancelWildcardCheck();
  1564. }
  1565. }
  1566. // Same tests as cancelWildcard for NSEC3-signed zone
  1567. TEST_F(InMemoryZoneFinderTest, cancelWildcardNSEC3) {
  1568. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1569. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
  1570. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1571. {
  1572. SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
  1573. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1574. }
  1575. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
  1576. {
  1577. SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
  1578. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1579. }
  1580. }
  1581. // Same tests as cancelWildcard for NSEC-signed zone. Check both cases with
  1582. // or without FIND_DNSSEC option. NSEC should be returned only when the option
  1583. // is given.
  1584. TEST_F(InMemoryZoneFinderTest, cancelWildcardNSEC) {
  1585. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1586. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
  1587. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1588. {
  1589. SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
  1590. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED,
  1591. ZoneFinder::FIND_DNSSEC);
  1592. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1593. }
  1594. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
  1595. {
  1596. SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
  1597. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED,
  1598. ZoneFinder::FIND_DNSSEC);
  1599. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1600. }
  1601. }
  1602. TEST_F(InMemoryZoneFinderTest, loadBadWildcard) {
  1603. // We reject loading the zone if it contains a wildcard name for
  1604. // NS or DNAME.
  1605. EXPECT_THROW(zone_finder_.add(rr_nswild_), InMemoryZoneFinder::AddError);
  1606. EXPECT_THROW(zone_finder_.add(rr_dnamewild_),
  1607. InMemoryZoneFinder::AddError);
  1608. }
  1609. TEST_F(InMemoryZoneFinderTest, swap) {
  1610. // build one zone finder with some data
  1611. InMemoryZoneFinder finder1(class_, origin_);
  1612. EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_));
  1613. EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_aaaa_));
  1614. // build another zone finder of a different RR class with some other data
  1615. const Name other_origin("version.bind");
  1616. ASSERT_NE(origin_, other_origin); // make sure these two are different
  1617. InMemoryZoneFinder finder2(RRClass::CH(), other_origin);
  1618. EXPECT_EQ(result::SUCCESS,
  1619. finder2.add(textToRRset("version.bind. 0 CH TXT \"test\"",
  1620. RRClass::CH())));
  1621. finder1.swap(finder2);
  1622. EXPECT_EQ(other_origin, finder1.getOrigin());
  1623. EXPECT_EQ(origin_, finder2.getOrigin());
  1624. EXPECT_EQ(RRClass::CH(), finder1.getClass());
  1625. EXPECT_EQ(RRClass::IN(), finder2.getClass());
  1626. // make sure the zone data is swapped, too
  1627. EXPECT_THROW(finder1.find(origin_, RRType::NS()), OutOfZone);
  1628. findTest(other_origin, RRType::TXT(), ZoneFinder::SUCCESS, false,
  1629. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &finder1);
  1630. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, false,
  1631. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &finder2);
  1632. EXPECT_THROW(finder2.find(other_origin, RRType::TXT()), OutOfZone);
  1633. }
  1634. TEST_F(InMemoryZoneFinderTest, getFileName) {
  1635. // for an empty zone the file name should also be empty.
  1636. EXPECT_TRUE(zone_finder_.getFileName().empty());
  1637. // if loading a zone fails the file name shouldn't be set.
  1638. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
  1639. MasterLoadError);
  1640. EXPECT_TRUE(zone_finder_.getFileName().empty());
  1641. // after a successful load, the specified file name should be set
  1642. InMemoryZoneFinder rootzone(class_, Name("."));
  1643. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  1644. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  1645. // overriding load, which will fail
  1646. EXPECT_THROW(rootzone.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  1647. MasterLoadError);
  1648. // the file name should be intact.
  1649. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  1650. // After swap, file names should also be swapped.
  1651. zone_finder_.swap(rootzone);
  1652. EXPECT_EQ(TEST_DATA_DIR "/root.zone", zone_finder_.getFileName());
  1653. EXPECT_TRUE(rootzone.getFileName().empty());
  1654. }
  1655. TEST_F(InMemoryZoneFinderTest, addRRsig) {
  1656. // A simple valid case: adding an RRset to be signed followed by an RRSIG
  1657. // that covers the first RRset
  1658. zone_finder_.add(rr_a_);
  1659. zone_finder_.add(textToRRset(rrsig_a_txt));
  1660. ZoneFinderContextPtr result = zone_finder_.find(origin_, RRType::A(),
  1661. ZoneFinder::FIND_DNSSEC);
  1662. EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
  1663. ASSERT_TRUE(result->rrset);
  1664. ASSERT_TRUE(result->rrset->getRRsig());
  1665. actual_rrsets_.push_back(result->rrset->getRRsig());
  1666. rrsetsCheck(rrsig_a_txt, actual_rrsets_.begin(), actual_rrsets_.end());
  1667. // Confirm a separate RRISG for a different type can be added
  1668. actual_rrsets_.clear();
  1669. zone_finder_.add(rr_ns_);
  1670. zone_finder_.add(textToRRset(rrsig_ns_txt));
  1671. result = zone_finder_.find(origin_, RRType::NS(), ZoneFinder::FIND_DNSSEC);
  1672. EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
  1673. ASSERT_TRUE(result->rrset);
  1674. ASSERT_TRUE(result->rrset->getRRsig());
  1675. actual_rrsets_.push_back(result->rrset->getRRsig());
  1676. rrsetsCheck(rrsig_ns_txt, actual_rrsets_.begin(), actual_rrsets_.end());
  1677. // Check a case with multiple RRSIGs
  1678. actual_rrsets_.clear();
  1679. zone_finder_.add(rr_ns_aaaa_);
  1680. zone_finder_.add(textToRRset(rrsig_aaaa_txt));
  1681. result = zone_finder_.find(Name("ns.example.org"), RRType::AAAA(),
  1682. ZoneFinder::FIND_DNSSEC);
  1683. EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
  1684. ASSERT_TRUE(result->rrset);
  1685. ASSERT_TRUE(result->rrset->getRRsig());
  1686. actual_rrsets_.push_back(result->rrset->getRRsig());
  1687. rrsetsCheck(rrsig_aaaa_txt, actual_rrsets_.begin(), actual_rrsets_.end());
  1688. }
  1689. TEST_F(InMemoryZoneFinderTest, addRRsigWithoutCovered) {
  1690. // The current implementation rejects attempts of adding RRSIG without
  1691. // covered RRsets already in the zone.
  1692. // Name doesn't exist
  1693. EXPECT_THROW(zone_finder_.add(
  1694. textToRRset("notexist.example.org. 300 IN RRSIG A 5 3 "
  1695. "3600 20000101000000 20000201000000 12345 "
  1696. "example.org. FAKEFAKEFAKE\n")),
  1697. InMemoryZoneFinder::AddError);
  1698. // Name exists, but is empty.
  1699. zone_finder_.add(rr_emptywild_);
  1700. EXPECT_THROW(zone_finder_.add(
  1701. textToRRset("foo.example.org. 300 IN RRSIG A 5 3 "
  1702. "3600 20000101000000 20000201000000 12345 "
  1703. "example.org. FAKEFAKEFAKE\n")),
  1704. InMemoryZoneFinder::AddError);
  1705. // Add RRSIG RRset without covered RR
  1706. zone_finder_.add(rr_a_);
  1707. EXPECT_THROW(zone_finder_.add(textToRRset(rrsig_ns_txt)),
  1708. InMemoryZoneFinder::AddError);
  1709. }
  1710. TEST_F(InMemoryZoneFinderTest, addbadRRsig) {
  1711. // Tests with other types of bogus input
  1712. // Empty RRSIG RRset.
  1713. EXPECT_THROW(zone_finder_.add(RRsetPtr(new RRset(origin_, class_,
  1714. RRType::RRSIG(),
  1715. RRTTL(300)))),
  1716. InMemoryZoneFinder::AddError);
  1717. // RRSIG with mixed covered types
  1718. zone_finder_.add(rr_a_); // make sure the covered name exists
  1719. // textToRRset() doesn't work as intended for this pathological case,
  1720. // so we need to construct the RRset by hand.
  1721. RRsetPtr rrset(new RRset(origin_, class_, RRType::RRSIG(), RRTTL(300)));
  1722. rrset->addRdata(generic::RRSIG("A 5 3 3600 20000101000000 20000201000000 "
  1723. "12345 example.org. FAKEFAKEFAKE"));
  1724. rrset->addRdata(generic::RRSIG("NS 5 3 3600 20000101000000 20000201000000 "
  1725. "54321 example.org. FAKEFAKEFAKEFAKE"));
  1726. EXPECT_THROW(zone_finder_.add(rrset), InMemoryZoneFinder::AddError);
  1727. // An attempt of overriding an existing RRSIG. The current implementation
  1728. // prohibits that.
  1729. zone_finder_.add(textToRRset(rrsig_a_txt));
  1730. EXPECT_THROW(zone_finder_.add(textToRRset(rrsig_a_txt)),
  1731. InMemoryZoneFinder::AddError);
  1732. }
  1733. TEST_F(InMemoryZoneFinderTest, addNSEC3) {
  1734. // Set up the faked hash calculator.
  1735. setNSEC3HashCreator(&nsec3_hash_creator_);
  1736. const string nsec3_text = string(apex_hash) + ".example.org." +
  1737. string(nsec3_common);
  1738. // This name shouldn't be found in the normal domain tree.
  1739. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
  1740. EXPECT_EQ(ZoneFinder::NXDOMAIN,
  1741. zone_finder_.find(Name(string(apex_hash) + ".example.org"),
  1742. RRType::NSEC3())->code);
  1743. // Dedicated NSEC3 find should be able to find it.
  1744. findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
  1745. zone_finder_.findNSEC3(Name("example.org"), false));
  1746. // This implementation rejects duplicate/update add of the same hash name
  1747. EXPECT_EQ(result::EXIST,
  1748. zone_finder_.add(textToRRset(
  1749. string(apex_hash) + ".example.org." +
  1750. string(nsec3_common) + " AAAA")));
  1751. // The original NSEC3 should be intact
  1752. findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
  1753. zone_finder_.findNSEC3(Name("example.org"), false));
  1754. // NSEC3-like name but of ordinary RR type should go to normal tree.
  1755. const string nonsec3_text = string(apex_hash) + ".example.org. " +
  1756. "300 IN A 192.0.2.1";
  1757. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nonsec3_text)));
  1758. EXPECT_EQ(ZoneFinder::SUCCESS,
  1759. zone_finder_.find(Name(string(apex_hash) + ".example.org"),
  1760. RRType::A())->code);
  1761. }
  1762. TEST_F(InMemoryZoneFinderTest, addNSEC3Lower) {
  1763. // Set up the faked hash calculator.
  1764. setNSEC3HashCreator(&nsec3_hash_creator_);
  1765. // Similar to the previous case, but NSEC3 owner name is lower-cased.
  1766. const string nsec3_text = string(apex_hash_lower) + ".example.org." +
  1767. string(nsec3_common);
  1768. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
  1769. findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
  1770. zone_finder_.findNSEC3(Name("example.org"), false));
  1771. }
  1772. TEST_F(InMemoryZoneFinderTest, addNSEC3Ordering) {
  1773. // Set up the faked hash calculator.
  1774. setNSEC3HashCreator(&nsec3_hash_creator_);
  1775. // Check that the internal storage ensures comparison based on the NSEC3
  1776. // semantics, regardless of the add order or the letter-case of hash.
  1777. // Adding "0P..", "2v..", then "2T..".
  1778. const string smallest = string(apex_hash) + ".example.org." +
  1779. string(nsec3_common);
  1780. const string middle = string(ns1_hash) + ".example.org." +
  1781. string(nsec3_common);
  1782. const string largest = string(xyw_hash) + ".example.org." +
  1783. string(nsec3_common);
  1784. zone_finder_.add(textToRRset(smallest));
  1785. zone_finder_.add(textToRRset(largest));
  1786. zone_finder_.add(textToRRset(middle));
  1787. // Then look for NSEC3 that covers a name whose hash is "2S.."
  1788. // The covering NSEC3 should be "0P.."
  1789. findNSEC3Check(false, 4, smallest, "",
  1790. zone_finder_.findNSEC3(Name("www.example.org"), false));
  1791. // Look for NSEC3 that covers names whose hash are "Q0.." and "0A.."
  1792. // The covering NSEC3 should be "2v.." in both cases
  1793. findNSEC3Check(false, 4, largest, "",
  1794. zone_finder_.findNSEC3(Name("xxx.example.org"), false));
  1795. findNSEC3Check(false, 4, largest, "",
  1796. zone_finder_.findNSEC3(Name("yyy.example.org"), false));
  1797. }
  1798. TEST_F(InMemoryZoneFinderTest, badNSEC3Name) {
  1799. // Our implementation refuses to load NSEC3 at a wildcard name
  1800. EXPECT_THROW(zone_finder_.add(textToRRset("*.example.org." +
  1801. string(nsec3_common))),
  1802. InMemoryZoneFinder::AddError);
  1803. // Likewise, if the owner name of NSEC3 has too many labels, it's refused.
  1804. EXPECT_THROW(zone_finder_.add(textToRRset("a." + string(apex_hash) +
  1805. ".example.org." +
  1806. string(nsec3_common))),
  1807. InMemoryZoneFinder::AddError);
  1808. }
  1809. TEST_F(InMemoryZoneFinderTest, addMultiNSEC3) {
  1810. // In this current implementation multiple NSEC3 RDATA isn't supported.
  1811. RRsetPtr nsec3(new RRset(Name(string(apex_hash) + ".example.org"),
  1812. RRClass::IN(), RRType::NSEC3(), RRTTL(300)));
  1813. nsec3->addRdata(
  1814. generic::NSEC3("1 0 12 aabbccdd 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A"));
  1815. nsec3->addRdata(
  1816. generic::NSEC3("1 1 1 ddccbbaa 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A"));
  1817. EXPECT_THROW(zone_finder_.add(nsec3), InMemoryZoneFinder::AddError);
  1818. }
  1819. TEST_F(InMemoryZoneFinderTest, addNSEC3WithRRSIG) {
  1820. // Set up the faked hash calculator.
  1821. setNSEC3HashCreator(&nsec3_hash_creator_);
  1822. // Adding NSEC3 and its RRSIG
  1823. const string nsec3_text = string(apex_hash) + ".example.org." +
  1824. string(nsec3_common);
  1825. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
  1826. const string nsec3_rrsig_text = string(apex_hash) + ".example.org." +
  1827. string(nsec3_rrsig_common);
  1828. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_rrsig_text)));
  1829. // Then look for it. The NSEC3 should have the RRSIG that was just added.
  1830. findNSEC3Check(true, origin_.getLabelCount(),
  1831. nsec3_text + "\n" + nsec3_rrsig_text, "",
  1832. zone_finder_.findNSEC3(Name("example.org"), false));
  1833. // Duplicate add of RRSIG for the same NSEC3 is prohibited.
  1834. EXPECT_THROW(zone_finder_.add(textToRRset(nsec3_rrsig_text)),
  1835. InMemoryZoneFinder::AddError);
  1836. // Same check using the lower-cased name. This also confirms matching
  1837. // is case-insensitive.
  1838. EXPECT_THROW(zone_finder_.add(textToRRset(string(apex_hash_lower) +
  1839. ".example.org."
  1840. + string(nsec3_rrsig_common))),
  1841. InMemoryZoneFinder::AddError);
  1842. }
  1843. TEST_F(InMemoryZoneFinderTest, badRRsigForNSEC3) {
  1844. // adding RRSIG for NSEC3 even before adding any NSEC3 (internally,
  1845. // a space for NSEC3 namespace isn't yet allocated)
  1846. EXPECT_THROW(zone_finder_.add(textToRRset(string(apex_hash) +
  1847. ".example.org." +
  1848. string(nsec3_rrsig_common))),
  1849. InMemoryZoneFinder::AddError);
  1850. // Add an NSEC3
  1851. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1852. textToRRset(string(apex_hash) + ".example.org." +
  1853. string(nsec3_common))));
  1854. // Then add an NSEC3 for a non existent NSEC3. It should fail in the
  1855. // current implementation.
  1856. EXPECT_THROW(zone_finder_.add(textToRRset(string(ns1_hash) +
  1857. ".example.org." +
  1858. string(nsec3_rrsig_common))),
  1859. InMemoryZoneFinder::AddError);
  1860. }
  1861. TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3PARAM) {
  1862. // First, add an NSEC3PARAM RR
  1863. EXPECT_EQ(result::SUCCESS,
  1864. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1865. "1 0 12 aabbccdd")));
  1866. // Adding an NSEC3 that has matching parameters is okay.
  1867. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1868. textToRRset(string(apex_hash) + ".example.org." +
  1869. string(nsec3_common))));
  1870. // NSEC3 with inconsistent parameter will be rejected
  1871. EXPECT_THROW(zone_finder_.add(
  1872. textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
  1873. "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
  1874. InMemoryZoneFinder::AddError);
  1875. }
  1876. TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3) {
  1877. // Add an NSEC3 without adding NSEC3PARAM
  1878. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1879. textToRRset(string(apex_hash) + ".example.org." +
  1880. string(nsec3_common))));
  1881. // Adding an NSEC3 with inconsistent parameter will be rejected at this pt.
  1882. EXPECT_THROW(zone_finder_.add(
  1883. textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
  1884. "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
  1885. InMemoryZoneFinder::AddError);
  1886. // Likewise, NSEC3PARAM with inconsistent parameter will be rejected.
  1887. EXPECT_THROW(zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1888. "1 0 1 aabbccdd")),
  1889. InMemoryZoneFinder::AddError);
  1890. }
  1891. TEST_F(InMemoryZoneFinderTest, multiNSEC3PARAM) {
  1892. // In this current implementation multiple NSEC3PARAM isn't supported.
  1893. RRsetPtr nsec3param(new RRset(Name("example.org"), RRClass::IN(),
  1894. RRType::NSEC3PARAM(), RRTTL(300)));
  1895. nsec3param->addRdata(generic::NSEC3PARAM("1 0 12 aabbccdd"));
  1896. nsec3param->addRdata(generic::NSEC3PARAM("1 1 1 ddccbbaa"));
  1897. EXPECT_THROW(zone_finder_.add(nsec3param), InMemoryZoneFinder::AddError);
  1898. }
  1899. TEST_F(InMemoryZoneFinderTest, nonOriginNSEC3PARAM) {
  1900. // This is a normal NSEC3PARAM at the zone origin
  1901. EXPECT_EQ(result::SUCCESS,
  1902. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1903. "1 0 12 aabbccdd")));
  1904. // Add another (with different param) at a non origin node. This is
  1905. // awkward, but the implementation accepts it as an ordinary RR.
  1906. EXPECT_EQ(result::SUCCESS,
  1907. zone_finder_.add(textToRRset("a.example.org. 300 IN NSEC3PARAM "
  1908. "1 1 1 aabbccdd")));
  1909. }
  1910. TEST_F(InMemoryZoneFinderTest, loadNSEC3Zone) {
  1911. // Check if it can load validly NSEC3-signed zone. At this moment
  1912. // it's sufficient to see it doesn't crash
  1913. zone_finder_.load(TEST_DATA_DIR "/example.org.nsec3-signed");
  1914. // Reload the zone with a version that doesn't have NSEC3PARAM.
  1915. // This is an abnormal case, but the implementation accepts it.
  1916. zone_finder_.load(TEST_DATA_DIR "/example.org.nsec3-signed-noparam");
  1917. }
  1918. // This test checks that the NSEC3 names don't really exist in the real
  1919. // namespace.
  1920. TEST_F(InMemoryZoneFinderTest, queryToNSEC3Name) {
  1921. // Add the NSEC3 and NSEC3PARAM there.
  1922. EXPECT_EQ(result::SUCCESS,
  1923. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1924. "1 0 12 aabbccdd")));
  1925. const Name nsec3domain(string(apex_hash) + ".example.org.");
  1926. // Adding an NSEC3 that has matching parameters is okay.
  1927. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1928. textToRRset(string(apex_hash) + ".example.org." +
  1929. string(nsec3_common))));
  1930. // Now, the domain should not exist
  1931. findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXDOMAIN, false,
  1932. ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
  1933. ZoneFinder::FIND_DNSSEC);
  1934. // If we add an A record, the domain should exist
  1935. ConstRRsetPtr rrset(textToRRset(string(apex_hash) +
  1936. ".example.org. 300 IN A 192.0.2.1"));
  1937. EXPECT_EQ(result::SUCCESS, zone_finder_.add(rrset));
  1938. // Searching for a different RRType will tell us this RRset doesn't exist
  1939. findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXRRSET, false,
  1940. ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
  1941. ZoneFinder::FIND_DNSSEC);
  1942. // Searching for the A record would find it
  1943. findTest(nsec3domain, RRType::A(), ZoneFinder::SUCCESS, true,
  1944. rrset, ZoneFinder::RESULT_DEFAULT, &zone_finder_,
  1945. ZoneFinder::FIND_DNSSEC);
  1946. }
  1947. // Continuation of the previous test (queryToNSEC3Name), we check we don't break
  1948. // the empty nonterminal case by existence of NSEC3 record with that name.
  1949. TEST_F(InMemoryZoneFinderTest, queryToNSEC3NameNonterminal) {
  1950. // Add the NSEC3 and NSEC3PARAM there.
  1951. EXPECT_EQ(result::SUCCESS,
  1952. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1953. "1 0 12 aabbccdd")));
  1954. const Name nsec3domain(string(apex_hash) + ".example.org.");
  1955. // Adding an NSEC3 that has matching parameters is okay.
  1956. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1957. textToRRset(string(apex_hash) + ".example.org." +
  1958. string(nsec3_common))));
  1959. // Something below the name
  1960. ConstRRsetPtr rrset(textToRRset("below." + string(apex_hash) +
  1961. ".example.org. 300 IN A 192.0.2.1"));
  1962. EXPECT_EQ(result::SUCCESS, zone_finder_.add(rrset));
  1963. // Now, the node is empty non-terminal.
  1964. findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXRRSET, false,
  1965. ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
  1966. ZoneFinder::FIND_DNSSEC);
  1967. }
  1968. TEST_F(InMemoryZoneFinderTest, findNSEC3) {
  1969. // Set up the faked hash calculator.
  1970. setNSEC3HashCreator(&nsec3_hash_creator_);
  1971. // Add a few NSEC3 records:
  1972. // apex (example.org.): hash=0P..
  1973. // ns1.example.org: hash=2T..
  1974. // w.example.org: hash=01..
  1975. // zzz.example.org: hash=R5..
  1976. const string apex_nsec3_text = string(apex_hash) + ".example.org." +
  1977. string(nsec3_common);
  1978. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(apex_nsec3_text)));
  1979. const string ns1_nsec3_text = string(ns1_hash) + ".example.org." +
  1980. string(nsec3_common);
  1981. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(ns1_nsec3_text)));
  1982. const string w_nsec3_text = string(w_hash) + ".example.org." +
  1983. string(nsec3_common);
  1984. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(w_nsec3_text)));
  1985. const string zzz_nsec3_text = string(zzz_hash) + ".example.org." +
  1986. string(nsec3_common);
  1987. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(zzz_nsec3_text)));
  1988. performNSEC3Test(zone_finder_);
  1989. }
  1990. TEST_F(InMemoryZoneFinderTest, findNSEC3ForBadZone) {
  1991. // Set up the faked hash calculator.
  1992. setNSEC3HashCreator(&nsec3_hash_creator_);
  1993. // If the zone has nothing about NSEC3 (neither NSEC3 or NSEC3PARAM),
  1994. // findNSEC3() should be rejected.
  1995. EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
  1996. DataSourceError);
  1997. // Only having NSEC3PARAM isn't enough
  1998. EXPECT_EQ(result::SUCCESS,
  1999. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  2000. "1 0 12 aabbccdd")));
  2001. EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
  2002. DataSourceError);
  2003. // Unless NSEC3 for apex is added the result in the recursive mode
  2004. // is guaranteed.
  2005. const string ns1_nsec3_text = string(ns1_hash) + ".example.org." +
  2006. string(nsec3_common);
  2007. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(ns1_nsec3_text)));
  2008. EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
  2009. DataSourceError);
  2010. }
  2011. TEST_F(InMemoryZoneFinderTest, loadAndFindNSEC3) {
  2012. // Using more realistic example, borrowed from RFC5155, with compliant
  2013. // hash calculator. We only confirm the data source can load it
  2014. // successfully and find correct NSEC3 RRs for some selected cases
  2015. // (detailed tests have been done above).
  2016. InMemoryZoneFinder finder(class_, Name("example"));
  2017. finder.load(TEST_DATA_COMMONDIR "/rfc5155-example.zone.signed");
  2018. // See RFC5155 B.1
  2019. ZoneFinder::FindNSEC3Result result1 =
  2020. finder.findNSEC3(Name("c.x.w.example"), true);
  2021. ASSERT_TRUE(result1.closest_proof);
  2022. // We compare closest_labels as int so the error report will be more
  2023. // readable in case it fails.
  2024. EXPECT_EQ(4, static_cast<int>(result1.closest_labels));
  2025. EXPECT_EQ(Name("b4um86eghhds6nea196smvmlo4ors995.example"),
  2026. result1.closest_proof->getName());
  2027. ASSERT_TRUE(result1.next_proof);
  2028. EXPECT_EQ(Name("0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example"),
  2029. result1.next_proof->getName());
  2030. // See RFC5155 B.2.
  2031. ZoneFinder::FindNSEC3Result result2 =
  2032. finder.findNSEC3(Name("ns1.example"), true);
  2033. ASSERT_TRUE(result2.closest_proof);
  2034. EXPECT_EQ(3, static_cast<int>(result2.closest_labels));
  2035. EXPECT_EQ(Name("2t7b4g4vsa5smi47k61mv5bv1a22bojr.example"),
  2036. result2.closest_proof->getName());
  2037. ASSERT_FALSE(result2.next_proof);
  2038. // See RFC5155 B.5.
  2039. ZoneFinder::FindNSEC3Result result3 =
  2040. finder.findNSEC3(Name("a.z.w.example"), true);
  2041. ASSERT_TRUE(result3.closest_proof);
  2042. EXPECT_EQ(3, static_cast<int>(result3.closest_labels));
  2043. EXPECT_EQ(Name("k8udemvp1j2f7eg6jebps17vp3n8i58h.example"),
  2044. result3.closest_proof->getName());
  2045. ASSERT_TRUE(result3.next_proof);
  2046. EXPECT_EQ(Name("q04jkcevqvmu85r014c7dkba38o0ji5r.example"),
  2047. result3.next_proof->getName());
  2048. }
  2049. }