memory_datasrc_unittest.cc 98 KB

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