query_unittest.cc 103 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366
  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 <sstream>
  15. #include <vector>
  16. #include <map>
  17. #include <boost/bind.hpp>
  18. #include <boost/scoped_ptr.hpp>
  19. #include <exceptions/exceptions.h>
  20. #include <dns/masterload.h>
  21. #include <dns/message.h>
  22. #include <dns/name.h>
  23. #include <dns/opcode.h>
  24. #include <dns/rcode.h>
  25. #include <dns/rrttl.h>
  26. #include <dns/rrtype.h>
  27. #include <dns/rdataclass.h>
  28. #include <datasrc/memory_datasrc.h>
  29. #include <auth/query.h>
  30. #include <testutils/dnsmessage_test.h>
  31. #include <gtest/gtest.h>
  32. using namespace std;
  33. using namespace isc::dns;
  34. using namespace isc::dns::rdata;
  35. using namespace isc::datasrc;
  36. using namespace isc::auth;
  37. using namespace isc::testutils;
  38. namespace {
  39. // This is the content of the mock zone (see below).
  40. // It's a sequence of textual RRs that is supposed to be parsed by
  41. // dns::masterLoad(). Some of the RRs are also used as the expected
  42. // data in specific tests, in which case they are referenced via specific
  43. // local variables (such as soa_txt).
  44. //
  45. // For readability consistency, all strings are placed in a separate line,
  46. // even if they are very short and can reasonably fit in a single line with
  47. // the corresponding variable. For example, we write
  48. // const char* const foo_txt =
  49. // "foo.example.com. 3600 IN AAAA 2001:db8::1\n";
  50. // instead of
  51. // const char* const foo_txt = "foo.example.com. 3600 IN AAAA 2001:db8::1\n";
  52. const char* const soa_txt =
  53. "example.com. 3600 IN SOA . . 0 0 0 0 0\n";
  54. const char* const zone_ns_txt =
  55. "example.com. 3600 IN NS glue.delegation.example.com.\n"
  56. "example.com. 3600 IN NS noglue.example.com.\n"
  57. "example.com. 3600 IN NS example.net.\n";
  58. const char* const zone_ds_txt =
  59. "example.com. 3600 IN DS 57855 5 1 "
  60. "B6DCD485719ADCA18E5F3D48A2331627FDD3 636B\n";
  61. const char* const ns_addrs_txt =
  62. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  63. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n"
  64. "noglue.example.com. 3600 IN A 192.0.2.53\n";
  65. const char* const delegation_txt =
  66. "delegation.example.com. 3600 IN NS glue.delegation.example.com.\n"
  67. "delegation.example.com. 3600 IN NS noglue.example.com.\n"
  68. "delegation.example.com. 3600 IN NS cname.example.com.\n"
  69. "delegation.example.com. 3600 IN NS example.org.\n";
  70. // Borrowed from the RFC4035
  71. const char* const delegation_ds_txt =
  72. "delegation.example.com. 3600 IN DS 57855 5 1 "
  73. "B6DCD485719ADCA18E5F3D48A2331627FDD3 636B\n";
  74. const char* const mx_txt =
  75. "mx.example.com. 3600 IN MX 10 www.example.com.\n"
  76. "mx.example.com. 3600 IN MX 20 mailer.example.org.\n"
  77. "mx.example.com. 3600 IN MX 30 mx.delegation.example.com.\n";
  78. const char* const www_a_txt =
  79. "www.example.com. 3600 IN A 192.0.2.80\n";
  80. const char* const cname_txt =
  81. "cname.example.com. 3600 IN CNAME www.example.com.\n";
  82. const char* const cname_nxdom_txt =
  83. "cnamenxdom.example.com. 3600 IN CNAME nxdomain.example.com.\n";
  84. // CNAME Leading out of zone
  85. const char* const cname_out_txt =
  86. "cnameout.example.com. 3600 IN CNAME www.example.org.\n";
  87. // The DNAME to do tests against
  88. const char* const dname_txt =
  89. "dname.example.com. 3600 IN DNAME "
  90. "somethinglong.dnametarget.example.com.\n";
  91. // Some data at the dname node (allowed by RFC 2672)
  92. const char* const dname_a_txt =
  93. "dname.example.com. 3600 IN A 192.0.2.5\n";
  94. // This is not inside the zone, this is created at runtime
  95. const char* const synthetized_cname_txt =
  96. "www.dname.example.com. 3600 IN CNAME "
  97. "www.somethinglong.dnametarget.example.com.\n";
  98. // The rest of data won't be referenced from the test cases.
  99. const char* const other_zone_rrs =
  100. "cnamemailer.example.com. 3600 IN CNAME www.example.com.\n"
  101. "cnamemx.example.com. 3600 IN MX 10 cnamemailer.example.com.\n"
  102. "mx.delegation.example.com. 3600 IN A 192.0.2.100\n";
  103. // Wildcards
  104. const char* const wild_txt =
  105. "*.wild.example.com. 3600 IN A 192.0.2.7\n";
  106. const char* const nsec_wild_txt =
  107. "*.wild.example.com. 3600 IN NSEC www.example.com. A NSEC RRSIG\n";
  108. const char* const cnamewild_txt =
  109. "*.cnamewild.example.com. 3600 IN CNAME www.example.org.\n";
  110. const char* const nsec_cnamewild_txt =
  111. "*.cnamewild.example.com. 3600 IN NSEC "
  112. "delegation.example.com. CNAME NSEC RRSIG\n";
  113. // Wildcard_nxrrset
  114. const char* const wild_txt_nxrrset =
  115. "*.uwild.example.com. 3600 IN A 192.0.2.9\n";
  116. const char* const nsec_wild_txt_nxrrset =
  117. "*.uwild.example.com. 3600 IN NSEC www.uwild.example.com. A NSEC RRSIG\n";
  118. const char* const wild_txt_next =
  119. "www.uwild.example.com. 3600 IN A 192.0.2.11\n";
  120. const char* const nsec_wild_txt_next =
  121. "www.uwild.example.com. 3600 IN NSEC *.wild.example.com. A NSEC RRSIG\n";
  122. // Wildcard empty
  123. const char* const empty_txt =
  124. "b.*.t.example.com. 3600 IN A 192.0.2.13\n";
  125. const char* const nsec_empty_txt =
  126. "b.*.t.example.com. 3600 IN NSEC *.uwild.example.com. A NSEC RRSIG\n";
  127. const char* const empty_prev_txt =
  128. "t.example.com. 3600 IN A 192.0.2.15\n";
  129. const char* const nsec_empty_prev_txt =
  130. "t.example.com. 3600 IN NSEC b.*.t.example.com. A NSEC RRSIG\n";
  131. // Used in NXDOMAIN proof test. We are going to test some unusual case where
  132. // the best possible wildcard is below the "next domain" of the NSEC RR that
  133. // proves the NXDOMAIN, i.e.,
  134. // mx.example.com. (exist)
  135. // (.no.example.com. (qname, NXDOMAIN)
  136. // ).no.example.com. (exist)
  137. // *.no.example.com. (best possible wildcard, not exist)
  138. const char* const no_txt =
  139. ").no.example.com. 3600 IN AAAA 2001:db8::53\n";
  140. // NSEC records.
  141. const char* const nsec_apex_txt =
  142. "example.com. 3600 IN NSEC cname.example.com. NS SOA NSEC RRSIG\n";
  143. const char* const nsec_mx_txt =
  144. "mx.example.com. 3600 IN NSEC ).no.example.com. MX NSEC RRSIG\n";
  145. const char* const nsec_no_txt =
  146. ").no.example.com. 3600 IN NSEC nz.no.example.com. AAAA NSEC RRSIG\n";
  147. // We'll also test the case where a single NSEC proves both NXDOMAIN and the
  148. // non existence of wildcard. The following records will be used for that
  149. // test.
  150. // ).no.example.com. (exist, whose NSEC proves everything)
  151. // *.no.example.com. (best possible wildcard, not exist)
  152. // nx.no.example.com. (NXDOMAIN)
  153. // nz.no.example.com. (exist)
  154. const char* const nz_txt =
  155. "nz.no.example.com. 3600 IN AAAA 2001:db8::5300\n";
  156. const char* const nsec_nz_txt =
  157. "nz.no.example.com. 3600 IN NSEC noglue.example.com. AAAA NSEC RRSIG\n";
  158. const char* const nsec_nxdomain_txt =
  159. "noglue.example.com. 3600 IN NSEC nonsec.example.com. A\n";
  160. // NSEC for the normal NXRRSET case
  161. const char* const nsec_www_txt =
  162. "www.example.com. 3600 IN NSEC example.com. A NSEC RRSIG\n";
  163. // Authoritative data without NSEC
  164. const char* const nonsec_a_txt =
  165. "nonsec.example.com. 3600 IN A 192.0.2.0\n";
  166. // NSEC3 RRs. You may also need to add mapping to MockZoneFinder::hash_map_.
  167. const char* const nsec3_apex_txt =
  168. "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example.com. 3600 IN NSEC3 1 1 12 "
  169. "aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA NSEC3PARAM RRSIG\n";
  170. const char* const nsec3_www_txt =
  171. "q04jkcevqvmu85r014c7dkba38o0ji5r.example.com. 3600 IN NSEC3 1 1 12 "
  172. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG\n";
  173. // NSEC3 for wild.example.com (used in wildcard tests, will be added on
  174. // demand not to confuse other tests)
  175. const char* const nsec3_atwild_txt =
  176. "ji6neoaepv8b5o6k4ev33abha8ht9fgc.example.com. 3600 IN NSEC3 1 1 12 "
  177. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en\n";
  178. // NSEC3 for cnamewild.example.com (used in wildcard tests, will be added on
  179. // demand not to confuse other tests)
  180. const char* const nsec3_atcnamewild_txt =
  181. "k8udemvp1j2f7eg6jebps17vp3n8i58h.example.com. 3600 IN NSEC3 1 1 12 "
  182. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en\n";
  183. // NSEC3 for *.uwild.example.com (will be added on demand not to confuse
  184. // other tests)
  185. const char* const nsec3_wild_txt =
  186. "b4um86eghhds6nea196smvmlo4ors995.example.com. 3600 IN NSEC3 1 1 12 "
  187. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG\n";
  188. // NSEC3 for uwild.example.com. (will be added on demand)
  189. const char* const nsec3_uwild_txt =
  190. "t644ebqk9bibcna874givr6joj62mlhv.example.com. 3600 IN NSEC3 1 1 12 "
  191. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG\n";
  192. // (Secure) delegation data; Delegation with DS record
  193. const char* const signed_delegation_txt =
  194. "signed-delegation.example.com. 3600 IN NS ns.example.net.\n";
  195. const char* const signed_delegation_ds_txt =
  196. "signed-delegation.example.com. 3600 IN DS 12345 8 2 "
  197. "764501411DE58E8618945054A3F620B36202E115D015A7773F4B78E0F952CECA\n";
  198. // (Secure) delegation data; Delegation without DS record (and both NSEC
  199. // and NSEC3 denying its existence)
  200. const char* const unsigned_delegation_txt =
  201. "unsigned-delegation.example.com. 3600 IN NS ns.example.net.\n";
  202. const char* const unsigned_delegation_nsec_txt =
  203. "unsigned-delegation.example.com. 3600 IN NSEC "
  204. "unsigned-delegation-optout.example.com. NS RRSIG NSEC\n";
  205. // This one will be added on demand
  206. const char* const unsigned_delegation_nsec3_txt =
  207. "q81r598950igr1eqvc60aedlq66425b5.example.com. 3600 IN NSEC3 1 1 12 "
  208. "aabbccdd 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom NS RRSIG\n";
  209. // Delegation without DS record, and no direct matching NSEC3 record
  210. const char* const unsigned_delegation_optout_txt =
  211. "unsigned-delegation-optout.example.com. 3600 IN NS ns.example.net.\n";
  212. const char* const unsigned_delegation_optout_nsec_txt =
  213. "unsigned-delegation-optout.example.com. 3600 IN NSEC "
  214. "*.uwild.example.com. NS RRSIG NSEC\n";
  215. // (Secure) delegation data; Delegation where the DS lookup will raise an
  216. // exception.
  217. const char* const bad_delegation_txt =
  218. "bad-delegation.example.com. 3600 IN NS ns.example.net.\n";
  219. // A helper function that generates a textual representation of RRSIG RDATA
  220. // for the given covered type. The resulting RRSIG may not necessarily make
  221. // sense in terms of the DNSSEC protocol, but for our testing purposes it's
  222. // okay.
  223. string
  224. getCommonRRSIGText(const string& type) {
  225. return (type +
  226. string(" 5 3 3600 20000101000000 20000201000000 12345 "
  227. "example.com. FAKEFAKEFAKE"));
  228. }
  229. // A helper callback of masterLoad() used in InMemoryZoneFinderTest.
  230. void
  231. setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
  232. *(*it) = rrset;
  233. ++it;
  234. }
  235. // A helper function that converts a textual form of a single RR into a
  236. // RRsetPtr object. If it's SOA, origin must be set to its owner name;
  237. // otherwise masterLoad() will reject it.
  238. RRsetPtr
  239. textToRRset(const string& text_rrset, const Name& origin = Name::ROOT_NAME()) {
  240. stringstream ss(text_rrset);
  241. RRsetPtr rrset;
  242. vector<RRsetPtr*> rrsets;
  243. rrsets.push_back(&rrset);
  244. masterLoad(ss, origin, RRClass::IN(),
  245. boost::bind(setRRset, _1, rrsets.begin()));
  246. return (rrset);
  247. }
  248. // This is a mock Zone Finder class for testing.
  249. // It is a derived class of ZoneFinder for the convenient of tests.
  250. // Its find() method emulates the common behavior of protocol compliant
  251. // ZoneFinder classes, but simplifies some minor cases and also supports broken
  252. // behavior.
  253. // For simplicity, most names are assumed to be "in zone"; delegations
  254. // to child zones are identified by the existence of non origin NS records.
  255. // Another special name is "dname.example.com". Query names under this name
  256. // will result in DNAME.
  257. // This mock zone doesn't handle empty non terminal nodes (if we need to test
  258. // such cases find() should have specialized code for it).
  259. class MockZoneFinder : public ZoneFinder {
  260. public:
  261. MockZoneFinder() :
  262. origin_(Name("example.com")),
  263. bad_signed_delegation_name_("bad-delegation.example.com"),
  264. dname_name_("dname.example.com"),
  265. has_SOA_(true),
  266. has_apex_NS_(true),
  267. rrclass_(RRClass::IN()),
  268. include_rrsig_anyway_(false),
  269. use_nsec3_(false),
  270. nsec_name_(origin_),
  271. nsec3_fake_(NULL),
  272. nsec3_name_(NULL)
  273. {
  274. stringstream zone_stream;
  275. zone_stream << soa_txt << zone_ns_txt << ns_addrs_txt <<
  276. delegation_txt << delegation_ds_txt << mx_txt << www_a_txt <<
  277. cname_txt << cname_nxdom_txt << cname_out_txt << dname_txt <<
  278. dname_a_txt << other_zone_rrs << no_txt << nz_txt <<
  279. nsec_apex_txt << nsec_mx_txt << nsec_no_txt << nsec_nz_txt <<
  280. nsec_nxdomain_txt << nsec_www_txt << nonsec_a_txt <<
  281. wild_txt << nsec_wild_txt << cnamewild_txt << nsec_cnamewild_txt <<
  282. wild_txt_nxrrset << nsec_wild_txt_nxrrset << wild_txt_next <<
  283. nsec_wild_txt_next << empty_txt << nsec_empty_txt <<
  284. empty_prev_txt << nsec_empty_prev_txt <<
  285. nsec3_apex_txt << nsec3_www_txt <<
  286. signed_delegation_txt << signed_delegation_ds_txt <<
  287. unsigned_delegation_txt << unsigned_delegation_nsec_txt <<
  288. unsigned_delegation_optout_txt <<
  289. unsigned_delegation_optout_nsec_txt <<
  290. bad_delegation_txt;
  291. masterLoad(zone_stream, origin_, rrclass_,
  292. boost::bind(&MockZoneFinder::loadRRset, this, _1));
  293. empty_nsec_rrset_ = ConstRRsetPtr(new RRset(Name::ROOT_NAME(),
  294. RRClass::IN(),
  295. RRType::NSEC(),
  296. RRTTL(3600)));
  297. // (Faked) NSEC3 hash map. For convenience we use hardcoded built-in
  298. // map instead of calculating and using actual hash.
  299. // The used hash values are borrowed from RFC5155 examples (they are
  300. // based on the query name, not that they would correspond directly
  301. // to the name).
  302. hash_map_[Name("example.com")] = "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom";
  303. hash_map_[Name("www.example.com")] =
  304. "q04jkcevqvmu85r014c7dkba38o0ji5r";
  305. hash_map_[Name("nxdomain.example.com")] =
  306. "v644ebqk9bibcna874givr6joj62mlhv";
  307. hash_map_[Name("nx.domain.example.com")] =
  308. "v644ebqk9bibcna874givr6joj62mlhv";
  309. hash_map_[Name("domain.example.com")] =
  310. "v644ebqk9bibcna874givr6joj62mlhv";
  311. hash_map_[Name("nxdomain2.example.com")] =
  312. "q00jkcevqvmu85r014c7dkba38o0ji5r";
  313. hash_map_[Name("nxdomain3.example.com")] =
  314. "009mhaveqvm6t7vbl5lop2u3t2rp3tom";
  315. hash_map_[Name("*.example.com")] =
  316. "r53bq7cc2uvmubfu5ocmm6pers9tk9en";
  317. hash_map_[Name("unsigned-delegation.example.com")] =
  318. "q81r598950igr1eqvc60aedlq66425b5"; // a bit larger than H(www)
  319. hash_map_[Name("*.uwild.example.com")] =
  320. "b4um86eghhds6nea196smvmlo4ors995";
  321. hash_map_[Name("unsigned-delegation-optout.example.com")] =
  322. "vld46lphhasfapj8og1pglgiasa5o5gt";
  323. // For wildcard proofs
  324. hash_map_[Name("wild.example.com")] =
  325. "ji6neoaepv8b5o6k4ev33abha8ht9fgc";
  326. hash_map_[Name("y.wild.example.com")] =
  327. "0p9mhaveqvm6t7vbl5lop2u3t2rp3ton"; // a bit larger than H(<apex>)
  328. hash_map_[Name("x.y.wild.example.com")] =
  329. "q04jkcevqvmu85r014c7dkba38o0ji6r"; // a bit larger than H(www)
  330. hash_map_[Name("cnamewild.example.com")] =
  331. "k8udemvp1j2f7eg6jebps17vp3n8i58h";
  332. hash_map_[Name("www.cnamewild.example.com")] =
  333. "q04jkcevqvmu85r014c7dkba38o0ji6r"; // a bit larger than H(www)
  334. // For closest encloser proof for www1.uwild.example.com:
  335. hash_map_[Name("uwild.example.com")] =
  336. "t644ebqk9bibcna874givr6joj62mlhv";
  337. hash_map_[Name("www1.uwild.example.com")] =
  338. "q04jkcevqvmu85r014c7dkba38o0ji6r"; // a bit larger than H(www)
  339. }
  340. virtual isc::dns::Name getOrigin() const { return (origin_); }
  341. virtual isc::dns::RRClass getClass() const { return (rrclass_); }
  342. virtual ZoneFinderContextPtr find(const isc::dns::Name& name,
  343. const isc::dns::RRType& type,
  344. const FindOptions options =
  345. FIND_DEFAULT);
  346. virtual ZoneFinderContextPtr findAll(const isc::dns::Name& name,
  347. std::vector<ConstRRsetPtr>& target,
  348. const FindOptions options =
  349. FIND_DEFAULT);
  350. virtual ZoneFinder::FindNSEC3Result
  351. findNSEC3(const Name& name, bool recursive);
  352. // If false is passed, it makes the zone broken as if it didn't have the
  353. // SOA.
  354. void setSOAFlag(bool on) { has_SOA_ = on; }
  355. // If false is passed, it makes the zone broken as if it didn't have
  356. // the apex NS.
  357. void setApexNSFlag(bool on) { has_apex_NS_ = on; }
  358. // Turn this on if you want it to return RRSIGs regardless of FIND_GLUE_OK
  359. void setIncludeRRSIGAnyway(bool on) { include_rrsig_anyway_ = on; }
  360. // Once called, this "faked" result will be returned when NSEC is expected
  361. // for the specified query name.
  362. void setNSECResult(const Name& nsec_name, Result code,
  363. ConstRRsetPtr rrset)
  364. {
  365. nsec_name_ = nsec_name;
  366. nsec_context_.reset(new Context(*this,
  367. FIND_DEFAULT, // a fake value
  368. ResultContext(code, rrset,
  369. RESULT_NSEC_SIGNED)));
  370. }
  371. // Once called, the findNSEC3 will return the provided result for the next
  372. // query. After that, it'll return to operate normally.
  373. // NULL disables. Does not take ownership of the pointer (it is generally
  374. // expected to be a local variable in the test function).
  375. void setNSEC3Result(const FindNSEC3Result* result,
  376. const Name* name = NULL)
  377. {
  378. nsec3_fake_ = result;
  379. nsec3_name_ = name;
  380. }
  381. // If true is passed return an empty NSEC3 RRset for some negative
  382. // answers when DNSSEC is required.
  383. void setNSEC3Flag(bool on) { use_nsec3_ = on; }
  384. virtual Name findPreviousName(const Name&) const {
  385. isc_throw(isc::NotImplemented, "Mock doesn't support previous name");
  386. }
  387. // This method allows tests to insert new record in the middle of the test.
  388. //
  389. // \param record_txt textual RR representation of RR (such as soa_txt, etc)
  390. void addRecord(const string& record_txt) {
  391. stringstream record_stream;
  392. record_stream << record_txt;
  393. masterLoad(record_stream, origin_, rrclass_,
  394. boost::bind(&MockZoneFinder::loadRRset, this, _1));
  395. }
  396. public:
  397. // We allow the tests to use these for convenience
  398. ConstRRsetPtr dname_rrset_; // could be used as an arbitrary bogus RRset
  399. ConstRRsetPtr empty_nsec_rrset_;
  400. protected:
  401. // A convenient shortcut. Will also be used by further derived mocks.
  402. ZoneFinderContextPtr createContext(FindOptions options,
  403. Result code,
  404. isc::dns::ConstRRsetPtr rrset,
  405. FindResultFlags flags = RESULT_DEFAULT)
  406. {
  407. return (ZoneFinderContextPtr(
  408. new Context(*this, options,
  409. ResultContext(code, rrset, flags))));
  410. }
  411. private:
  412. typedef map<RRType, ConstRRsetPtr> RRsetStore;
  413. typedef map<Name, RRsetStore> Domains;
  414. Domains domains_;
  415. Domains delegations_;
  416. Domains nsec3_domains_;
  417. // This is used to identify delegation to a child zone, and used to
  418. // find a matching entry in delegations_. Note that first found entry
  419. // is returned, so it's not a longest match. Test data must be set up
  420. // to ensure the first match is always the longest match.
  421. struct SubdomainMatch {
  422. SubdomainMatch(const Name& name) : name_(name) {}
  423. bool operator()(const pair<Name, RRsetStore>& domain_elem) const {
  424. return (name_ == domain_elem.first ||
  425. name_.compare(domain_elem.first).getRelation() ==
  426. NameComparisonResult::SUBDOMAIN);
  427. }
  428. private:
  429. const Name& name_;
  430. };
  431. void loadRRset(RRsetPtr rrset) {
  432. if (rrset->getType() == RRType::NSEC3()) {
  433. // NSEC3 should go to the dedicated table
  434. nsec3_domains_[rrset->getName()][rrset->getType()] = rrset;
  435. // By nature it should have RRSIG. (We may want to selectively
  436. // omit this to test pathological cases).
  437. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  438. getCommonRRSIGText(rrset->getType().
  439. toText()))));
  440. return;
  441. }
  442. domains_[rrset->getName()][rrset->getType()] = rrset;
  443. // Remember delegation (NS/DNAME) related RRsets separately.
  444. if (rrset->getType() == RRType::NS() && rrset->getName() != origin_) {
  445. delegations_[rrset->getName()][rrset->getType()] = rrset;
  446. } else if (rrset->getName() == dname_name_ &&
  447. rrset->getType() == RRType::DNAME()) {
  448. dname_rrset_ = rrset;
  449. }
  450. // Add some signatures. For NS, we only have RRSIG for the origin
  451. // name. For others generate RRSIG unconditionally. Technically this
  452. // is wrong because we shouldn't have it for names under a zone
  453. // cut. But in our tests that doesn't matter, so we add them
  454. // just for simplicity.
  455. // Note that this includes RRSIG for DS with secure delegations.
  456. // They should have RRSIGs, so that's actually expected data, not just
  457. // for simplicity.
  458. if (rrset->getType() != RRType::NS() || rrset->getName() == origin_) {
  459. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  460. getCommonRRSIGText(rrset->getType().
  461. toText()))));
  462. }
  463. }
  464. const Name origin_;
  465. // Names where we delegate somewhere else
  466. const Name bad_signed_delegation_name_;
  467. const Name dname_name_;
  468. bool has_SOA_;
  469. bool has_apex_NS_;
  470. const RRClass rrclass_;
  471. bool include_rrsig_anyway_;
  472. bool use_nsec3_;
  473. // The following two will be used for faked NSEC cases
  474. Name nsec_name_;
  475. ZoneFinderContextPtr nsec_context_;
  476. // The following two are for faking bad NSEC3 responses
  477. // Enabled when not NULL
  478. const FindNSEC3Result* nsec3_fake_;
  479. const Name* nsec3_name_;
  480. public:
  481. // Public, to allow tests looking up the right names for something
  482. map<Name, string> hash_map_;
  483. };
  484. // A helper function that generates a new RRset based on "wild_rrset",
  485. // replacing its owner name with 'real_name'.
  486. ConstRRsetPtr
  487. substituteWild(const AbstractRRset& wild_rrset, const Name& real_name) {
  488. RRsetPtr rrset(new RRset(real_name, wild_rrset.getClass(),
  489. wild_rrset.getType(), wild_rrset.getTTL()));
  490. // For simplicity we only consider the case with one RDATA (for now)
  491. rrset->addRdata(wild_rrset.getRdataIterator()->getCurrent());
  492. ConstRRsetPtr wild_sig = wild_rrset.getRRsig();
  493. if (wild_sig) {
  494. RRsetPtr sig(new RRset(real_name, wild_sig->getClass(),
  495. wild_sig->getType(), wild_sig->getTTL()));
  496. sig->addRdata(wild_sig->getRdataIterator()->getCurrent());
  497. rrset->addRRsig(sig);
  498. }
  499. return (rrset);
  500. }
  501. ZoneFinderContextPtr
  502. MockZoneFinder::findAll(const Name& name, std::vector<ConstRRsetPtr>& target,
  503. const FindOptions options)
  504. {
  505. ZoneFinderContextPtr result(find(name, RRType::ANY(), options));
  506. if (result->code == NXRRSET) {
  507. const Domains::const_iterator found_domain = domains_.find(name);
  508. if (!found_domain->second.empty()) {
  509. for (RRsetStore::const_iterator found_rrset =
  510. found_domain->second.begin();
  511. found_rrset != found_domain->second.end(); ++found_rrset) {
  512. // Insert RRs under the domain name into target
  513. target.push_back(found_rrset->second);
  514. }
  515. return (ZoneFinderContextPtr(
  516. new Context(*this, options,
  517. ResultContext(SUCCESS, RRsetPtr()),
  518. target)));
  519. }
  520. }
  521. return (result);
  522. }
  523. ZoneFinder::FindNSEC3Result
  524. MockZoneFinder::findNSEC3(const Name& name, bool recursive) {
  525. // Do we have a fake result set? If so, use it.
  526. if (nsec3_fake_ != NULL &&
  527. (nsec3_name_ == NULL || *nsec3_name_ == name)) {
  528. const FindNSEC3Result* result(nsec3_fake_);
  529. return (*result);
  530. }
  531. ConstRRsetPtr covering_proof;
  532. const int labels = name.getLabelCount();
  533. // For brevity, we assume several things below: maps should have an
  534. // expected entry when operator[] is used; maps are not empty.
  535. for (int i = 0; i < labels; ++i) {
  536. const string hlabel = hash_map_[name.split(i, labels - i)];
  537. if (hlabel.empty()) {
  538. isc_throw(isc::Unexpected, "findNSEC3() hash failure for " <<
  539. name.split(i, labels - i));
  540. }
  541. const Name hname = Name(hlabel + ".example.com");
  542. // We don't use const_iterator so that we can use operator[] below
  543. Domains::iterator found_domain = nsec3_domains_.lower_bound(hname);
  544. // If the given hash is larger than the largest stored hash or
  545. // the first label doesn't match the target, identify the "previous"
  546. // hash value and remember it as the candidate next closer proof.
  547. if (found_domain == nsec3_domains_.end() ||
  548. found_domain->first.split(0, 1).toText(true) != hlabel) {
  549. // If the given hash is larger or smaller than everything,
  550. // the covering proof is the NSEC3 that has the largest hash.
  551. if (found_domain == nsec3_domains_.end() ||
  552. found_domain == nsec3_domains_.begin()) {
  553. covering_proof =
  554. nsec3_domains_.rbegin()->second[RRType::NSEC3()];
  555. } else {
  556. // Otherwise, H(found_domain-1) < given_hash < H(found_domain)
  557. // The covering proof is the first one.
  558. covering_proof = (--found_domain)->second[RRType::NSEC3()];
  559. }
  560. if (!recursive) { // in non recursive mode, we are done.
  561. return (ZoneFinder::FindNSEC3Result(false,
  562. name.getLabelCount(),
  563. covering_proof,
  564. ConstRRsetPtr()));
  565. }
  566. } else { // exact match
  567. return (ZoneFinder::FindNSEC3Result(
  568. true, name.getLabelCount() - i,
  569. found_domain->second[RRType::NSEC3()],
  570. covering_proof));
  571. }
  572. }
  573. isc_throw(isc::Unexpected, "findNSEC3() isn't expected to fail");
  574. }
  575. ZoneFinderContextPtr
  576. MockZoneFinder::find(const Name& name, const RRType& type,
  577. const FindOptions options)
  578. {
  579. // Emulating a broken zone: mandatory apex RRs are missing if specifically
  580. // configured so (which are rare cases).
  581. if (name == origin_ && type == RRType::SOA() && !has_SOA_) {
  582. return (createContext(options, NXDOMAIN, RRsetPtr()));
  583. } else if (name == origin_ && type == RRType::NS() && !has_apex_NS_) {
  584. return (createContext(options, NXDOMAIN, RRsetPtr()));
  585. }
  586. // Special case for names on or under a zone cut and under DNAME
  587. Domains::iterator it;
  588. if ((options & FIND_GLUE_OK) == 0 &&
  589. (it = find_if(delegations_.begin(), delegations_.end(),
  590. SubdomainMatch(name))) != delegations_.end()) {
  591. ConstRRsetPtr delegation_ns = it->second[RRType::NS()];
  592. assert(delegation_ns); // should be ensured by how we construct it
  593. // DS query for the delegated domain (i.e. an exact match) will be
  594. // handled just like an in-zone case below. Others result in
  595. // DELEGATION.
  596. if (type != RRType::DS() || it->first != name) {
  597. return (createContext(options, DELEGATION, delegation_ns));
  598. }
  599. } else if (name.compare(dname_name_).getRelation() ==
  600. NameComparisonResult::SUBDOMAIN) {
  601. return (createContext(options, DNAME, dname_rrset_));
  602. }
  603. // normal cases. names are searched for only per exact-match basis
  604. // for simplicity.
  605. const Domains::const_iterator found_domain = domains_.find(name);
  606. if (found_domain != domains_.end()) {
  607. // First, try exact match.
  608. RRsetStore::const_iterator found_rrset =
  609. found_domain->second.find(type);
  610. if (found_rrset != found_domain->second.end()) {
  611. ConstRRsetPtr rrset;
  612. // Strip whatever signature there is in case DNSSEC is not required
  613. // Just to make sure the Query asks for it when it is needed
  614. if ((options & ZoneFinder::FIND_DNSSEC) != 0 ||
  615. include_rrsig_anyway_ ||
  616. !found_rrset->second->getRRsig()) {
  617. rrset = found_rrset->second;
  618. } else {
  619. RRsetPtr noconst(new RRset(found_rrset->second->getName(),
  620. found_rrset->second->getClass(),
  621. found_rrset->second->getType(),
  622. found_rrset->second->getTTL()));
  623. for (RdataIteratorPtr
  624. i(found_rrset->second->getRdataIterator());
  625. !i->isLast(); i->next()) {
  626. noconst->addRdata(i->getCurrent());
  627. }
  628. rrset = noconst;
  629. }
  630. return (createContext(options, SUCCESS, rrset));
  631. }
  632. // Otherwise, if this domain name has CNAME, return it.
  633. found_rrset = found_domain->second.find(RRType::CNAME());
  634. if (found_rrset != found_domain->second.end()) {
  635. return (createContext(options, CNAME, found_rrset->second));
  636. }
  637. // Otherwise it's NXRRSET case...
  638. // ...but a special pathological case first:
  639. if (found_domain->first == bad_signed_delegation_name_ &&
  640. type == RRType::DS()) {
  641. return (createContext(options, NXDOMAIN, RRsetPtr()));
  642. }
  643. // normal cases follow.
  644. if ((options & FIND_DNSSEC) != 0) {
  645. if (use_nsec3_) {
  646. return (createContext(options, NXRRSET, RRsetPtr(),
  647. RESULT_NSEC3_SIGNED));
  648. }
  649. found_rrset = found_domain->second.find(RRType::NSEC());
  650. if (found_rrset != found_domain->second.end()) {
  651. return (createContext(options, NXRRSET, found_rrset->second,
  652. RESULT_NSEC_SIGNED));
  653. }
  654. }
  655. return (createContext(options, NXRRSET, RRsetPtr(),
  656. RESULT_NSEC_SIGNED));
  657. }
  658. // query name isn't found in our domains.
  659. // We first check if the query name is an empty non terminal name
  660. // of the zone by naive linear search.
  661. Domains::const_iterator domain;
  662. for (domain = domains_.begin(); domain != domains_.end(); ++domain) {
  663. if (name.compare((*domain).first).getRelation() ==
  664. NameComparisonResult::SUPERDOMAIN) {
  665. break;
  666. }
  667. }
  668. if (domain != domains_.end()) {
  669. // The query name is in an empty non terminal node followed by 'domain'
  670. // (for simplicity we ignore the pathological case of 'domain' is
  671. // the origin of the zone)
  672. --domain; // reset domain to the "previous name"
  673. if ((options & FIND_DNSSEC) != 0) {
  674. if (use_nsec3_) {
  675. return (createContext(options, NXRRSET, RRsetPtr(),
  676. RESULT_NSEC3_SIGNED));
  677. }
  678. RRsetStore::const_iterator found_rrset =
  679. (*domain).second.find(RRType::NSEC());
  680. if (found_rrset != (*domain).second.end()) {
  681. return (createContext(options, NXRRSET, found_rrset->second,
  682. RESULT_NSEC_SIGNED));
  683. }
  684. }
  685. return (createContext(options, NXRRSET, RRsetPtr()));
  686. }
  687. // Another possibility is wildcard. For simplicity we only check
  688. // hardcoded specific cases, ignoring other details such as canceling
  689. // due to the existence of closer name.
  690. if ((options & NO_WILDCARD) == 0) {
  691. const Name wild_suffix(name == Name("x.y.wild.example.com") ?
  692. Name("wild.example.com") : name.split(1));
  693. // Unit Tests use those domains for Wildcard test.
  694. if (name.equals(Name("www.wild.example.com")) ||
  695. name.equals(Name("x.y.wild.example.com")) ||
  696. name.equals(Name("www1.uwild.example.com")) ||
  697. name.equals(Name("a.t.example.com"))) {
  698. if (name.compare(wild_suffix).getRelation() ==
  699. NameComparisonResult::SUBDOMAIN) {
  700. domain = domains_.find(Name("*").concatenate(wild_suffix));
  701. // Matched the QNAME
  702. if (domain != domains_.end()) {
  703. RRsetStore::const_iterator found_rrset =
  704. domain->second.find(type);
  705. // Matched the QTYPE
  706. if(found_rrset != domain->second.end()) {
  707. return (createContext(options,SUCCESS, substituteWild(
  708. *found_rrset->second, name),
  709. RESULT_WILDCARD |
  710. (use_nsec3_ ?
  711. RESULT_NSEC3_SIGNED :
  712. RESULT_NSEC_SIGNED)));
  713. } else {
  714. // No matched QTYPE, this case is for NXRRSET with
  715. // WILDCARD
  716. if (use_nsec3_) {
  717. return (createContext(options, NXRRSET, RRsetPtr(),
  718. RESULT_WILDCARD |
  719. RESULT_NSEC3_SIGNED));
  720. }
  721. const Name new_name =
  722. Name("*").concatenate(wild_suffix);
  723. found_rrset = domain->second.find(RRType::NSEC());
  724. assert(found_rrset != domain->second.end());
  725. return (createContext(options, NXRRSET, substituteWild(
  726. *found_rrset->second,
  727. new_name),
  728. RESULT_WILDCARD |
  729. RESULT_NSEC_SIGNED));
  730. }
  731. } else {
  732. // This is empty non terminal name case on wildcard.
  733. const Name empty_name = Name("*").concatenate(wild_suffix);
  734. if (use_nsec3_) {
  735. return (createContext(options, NXRRSET, RRsetPtr(),
  736. RESULT_WILDCARD |
  737. RESULT_NSEC3_SIGNED));
  738. }
  739. for (Domains::reverse_iterator it = domains_.rbegin();
  740. it != domains_.rend();
  741. ++it) {
  742. RRsetStore::const_iterator nsec_it;
  743. if ((*it).first < empty_name &&
  744. (nsec_it = (*it).second.find(RRType::NSEC()))
  745. != (*it).second.end()) {
  746. return (createContext(options, NXRRSET,
  747. (*nsec_it).second,
  748. RESULT_WILDCARD |
  749. RESULT_NSEC_SIGNED));
  750. }
  751. }
  752. }
  753. return (createContext(options, NXRRSET, RRsetPtr(),
  754. RESULT_WILDCARD));
  755. }
  756. }
  757. const Name cnamewild_suffix("cnamewild.example.com");
  758. if (name.compare(cnamewild_suffix).getRelation() ==
  759. NameComparisonResult::SUBDOMAIN) {
  760. domain = domains_.find(Name("*").concatenate(cnamewild_suffix));
  761. assert(domain != domains_.end());
  762. RRsetStore::const_iterator found_rrset =
  763. domain->second.find(RRType::CNAME());
  764. assert(found_rrset != domain->second.end());
  765. return (createContext(options, CNAME,
  766. substituteWild(*found_rrset->second, name),
  767. RESULT_WILDCARD |
  768. (use_nsec3_ ? RESULT_NSEC3_SIGNED :
  769. RESULT_NSEC_SIGNED)));
  770. }
  771. }
  772. // This is an NXDOMAIN case.
  773. // If we need DNSSEC proof, find the "previous name" that has an NSEC RR
  774. // and return NXDOMAIN with the found NSEC. Otherwise, just return the
  775. // NXDOMAIN code and NULL. If DNSSEC proof is requested but no NSEC is
  776. // found, we return NULL, too. (For simplicity under the test conditions
  777. // we don't care about pathological cases such as the name is "smaller"
  778. // than the origin)
  779. if ((options & FIND_DNSSEC) != 0) {
  780. if (use_nsec3_) {
  781. return (createContext(options, NXDOMAIN, RRsetPtr(),
  782. RESULT_NSEC3_SIGNED));
  783. }
  784. // Emulate a broken DataSourceClient for some special names.
  785. if (nsec_context_ && nsec_name_ == name) {
  786. return (nsec_context_);
  787. }
  788. // Normal case
  789. // XXX: some older g++ complains about operator!= if we use
  790. // const_reverse_iterator
  791. for (Domains::reverse_iterator it = domains_.rbegin();
  792. it != domains_.rend();
  793. ++it) {
  794. RRsetStore::const_iterator nsec_it;
  795. if ((*it).first < name &&
  796. (nsec_it = (*it).second.find(RRType::NSEC()))
  797. != (*it).second.end()) {
  798. return (createContext(options, NXDOMAIN, (*nsec_it).second,
  799. RESULT_NSEC_SIGNED));
  800. }
  801. }
  802. }
  803. return (createContext(options,NXDOMAIN, RRsetPtr()));
  804. }
  805. class QueryTest : public ::testing::Test {
  806. protected:
  807. QueryTest() :
  808. qname(Name("www.example.com")), qclass(RRClass::IN()),
  809. qtype(RRType::A()), response(Message::RENDER),
  810. qid(response.getQid()), query_code(Opcode::QUERY().getCode()),
  811. ns_addrs_and_sig_txt(string(ns_addrs_txt) +
  812. "glue.delegation.example.com. 3600 IN RRSIG " +
  813. getCommonRRSIGText("A") + "\n" +
  814. "glue.delegation.example.com. 3600 IN RRSIG " +
  815. getCommonRRSIGText("AAAA") + "\n" +
  816. "noglue.example.com. 3600 IN RRSIG " +
  817. getCommonRRSIGText("A"))
  818. {
  819. response.setRcode(Rcode::NOERROR());
  820. response.setOpcode(Opcode::QUERY());
  821. // create and add a matching zone.
  822. mock_finder = new MockZoneFinder();
  823. memory_client.addZone(ZoneFinderPtr(mock_finder));
  824. }
  825. MockZoneFinder* mock_finder;
  826. // We use InMemoryClient here. We could have some kind of mock client
  827. // here, but historically, the Query supported only InMemoryClient
  828. // (originally named MemoryDataSrc) and was tested with it, so we keep
  829. // it like this for now.
  830. InMemoryClient memory_client;
  831. const Name qname;
  832. const RRClass qclass;
  833. const RRType qtype;
  834. Message response;
  835. const qid_t qid;
  836. const uint16_t query_code;
  837. const string ns_addrs_and_sig_txt; // convenient shortcut
  838. };
  839. // A wrapper to check resulting response message commonly used in
  840. // tests below.
  841. // check_origin needs to be specified only when the authority section has
  842. // an SOA RR. The interface is not generic enough but should be okay
  843. // for our test cases in practice.
  844. void
  845. responseCheck(Message& response, const isc::dns::Rcode& rcode,
  846. unsigned int flags, const unsigned int ancount,
  847. const unsigned int nscount, const unsigned int arcount,
  848. const char* const expected_answer,
  849. const char* const expected_authority,
  850. const char* const expected_additional,
  851. const Name& check_origin = Name::ROOT_NAME())
  852. {
  853. // In our test cases QID, Opcode, and QDCOUNT should be constant, so
  854. // we don't bother the test cases specifying these values.
  855. headerCheck(response, response.getQid(), rcode, Opcode::QUERY().getCode(),
  856. flags, 0, ancount, nscount, arcount);
  857. if (expected_answer != NULL) {
  858. rrsetsCheck(expected_answer,
  859. response.beginSection(Message::SECTION_ANSWER),
  860. response.endSection(Message::SECTION_ANSWER),
  861. check_origin);
  862. }
  863. if (expected_authority != NULL) {
  864. rrsetsCheck(expected_authority,
  865. response.beginSection(Message::SECTION_AUTHORITY),
  866. response.endSection(Message::SECTION_AUTHORITY),
  867. check_origin);
  868. }
  869. if (expected_additional != NULL) {
  870. rrsetsCheck(expected_additional,
  871. response.beginSection(Message::SECTION_ADDITIONAL),
  872. response.endSection(Message::SECTION_ADDITIONAL));
  873. }
  874. }
  875. TEST_F(QueryTest, noZone) {
  876. // There's no zone in the memory datasource. So the response should have
  877. // REFUSED.
  878. InMemoryClient empty_memory_client;
  879. Query nozone_query(&empty_memory_client, qname, qtype, &response);
  880. EXPECT_NO_THROW(nozone_query.process());
  881. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  882. }
  883. TEST_F(QueryTest, exactMatch) {
  884. Query query(&memory_client, qname, qtype, &response);
  885. EXPECT_NO_THROW(query.process());
  886. // find match rrset
  887. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  888. www_a_txt, zone_ns_txt, ns_addrs_txt);
  889. }
  890. TEST_F(QueryTest, exactMatchMultipleQueries) {
  891. Query query(&memory_client, qname, qtype, &response);
  892. EXPECT_NO_THROW(query.process());
  893. // find match rrset
  894. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  895. www_a_txt, zone_ns_txt, ns_addrs_txt);
  896. response.clear(isc::dns::Message::RENDER);
  897. response.setRcode(Rcode::NOERROR());
  898. response.setOpcode(Opcode::QUERY());
  899. query.reset(&memory_client, qname, qtype, &response);
  900. EXPECT_NO_THROW(query.process());
  901. // find match rrset
  902. SCOPED_TRACE("Second query");
  903. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  904. www_a_txt, zone_ns_txt, ns_addrs_txt);
  905. }
  906. TEST_F(QueryTest, exactMatchIgnoreSIG) {
  907. // Check that we do not include the RRSIG when not requested even when
  908. // we receive it from the data source.
  909. mock_finder->setIncludeRRSIGAnyway(true);
  910. Query query(&memory_client, qname, qtype, &response);
  911. EXPECT_NO_THROW(query.process());
  912. // find match rrset
  913. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  914. www_a_txt, zone_ns_txt, ns_addrs_txt);
  915. }
  916. TEST_F(QueryTest, dnssecPositive) {
  917. // Just like exactMatch, but the signatures should be included as well
  918. Query query(&memory_client, qname, qtype, &response, true);
  919. EXPECT_NO_THROW(query.process());
  920. // find match rrset
  921. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 4, 6,
  922. (www_a_txt + std::string("www.example.com. 3600 IN RRSIG "
  923. "A 5 3 3600 20000101000000 "
  924. "20000201000000 12345 example.com. "
  925. "FAKEFAKEFAKE\n")).c_str(),
  926. (zone_ns_txt + std::string("example.com. 3600 IN RRSIG NS 5 "
  927. "3 3600 20000101000000 "
  928. "20000201000000 12345 "
  929. "example.com. FAKEFAKEFAKE\n")).
  930. c_str(),
  931. ns_addrs_and_sig_txt.c_str());
  932. }
  933. TEST_F(QueryTest, exactAddrMatch) {
  934. // find match rrset, omit additional data which has already been provided
  935. // in the answer section from the additional.
  936. EXPECT_NO_THROW(Query(&memory_client, Name("noglue.example.com"), qtype,
  937. &response).process());
  938. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 2,
  939. "noglue.example.com. 3600 IN A 192.0.2.53\n", zone_ns_txt,
  940. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  941. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
  942. }
  943. TEST_F(QueryTest, apexNSMatch) {
  944. // find match rrset, omit authority data which has already been provided
  945. // in the answer section from the authority section.
  946. EXPECT_NO_THROW(Query(&memory_client, Name("example.com"), RRType::NS(),
  947. &response).process());
  948. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 3, 0, 3,
  949. zone_ns_txt, NULL, ns_addrs_txt);
  950. }
  951. // test type any query logic
  952. TEST_F(QueryTest, exactAnyMatch) {
  953. // find match rrset, omit additional data which has already been provided
  954. // in the answer section from the additional.
  955. EXPECT_NO_THROW(Query(&memory_client, Name("noglue.example.com"),
  956. RRType::ANY(), &response).process());
  957. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 3, 2,
  958. (string("noglue.example.com. 3600 IN A 192.0.2.53\n") +
  959. string(nsec_nxdomain_txt)).c_str(),
  960. zone_ns_txt,
  961. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  962. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
  963. }
  964. TEST_F(QueryTest, apexAnyMatch) {
  965. // find match rrset, omit additional data which has already been provided
  966. // in the answer section from the additional.
  967. EXPECT_NO_THROW(Query(&memory_client, Name("example.com"),
  968. RRType::ANY(), &response).process());
  969. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 5, 0, 3,
  970. (string(soa_txt) + string(zone_ns_txt) +
  971. string(nsec_apex_txt)).c_str(),
  972. NULL, ns_addrs_txt, mock_finder->getOrigin());
  973. }
  974. TEST_F(QueryTest, mxANYMatch) {
  975. EXPECT_NO_THROW(Query(&memory_client, Name("mx.example.com"),
  976. RRType::ANY(), &response).process());
  977. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 4, 3, 4,
  978. (string(mx_txt) + string(nsec_mx_txt)).c_str(), zone_ns_txt,
  979. (string(ns_addrs_txt) + string(www_a_txt)).c_str());
  980. }
  981. TEST_F(QueryTest, glueANYMatch) {
  982. EXPECT_NO_THROW(Query(&memory_client, Name("delegation.example.com"),
  983. RRType::ANY(), &response).process());
  984. responseCheck(response, Rcode::NOERROR(), 0, 0, 4, 3,
  985. NULL, delegation_txt, ns_addrs_txt);
  986. }
  987. TEST_F(QueryTest, nodomainANY) {
  988. EXPECT_NO_THROW(Query(&memory_client, Name("nxdomain.example.com"),
  989. RRType::ANY(), &response).process());
  990. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 1, 0,
  991. NULL, soa_txt, NULL, mock_finder->getOrigin());
  992. }
  993. TEST_F(QueryTest, badInitialization) {
  994. Query query;
  995. EXPECT_THROW(query.process(), isc::InvalidOperation);
  996. }
  997. // This tests that when we need to look up Zone's apex NS records for
  998. // authoritative answer, and there is no apex NS records. It should
  999. // throw in that case.
  1000. TEST_F(QueryTest, noApexNS) {
  1001. // Disable apex NS record
  1002. mock_finder->setApexNSFlag(false);
  1003. EXPECT_THROW(Query(&memory_client, Name("noglue.example.com"), qtype,
  1004. &response).process(), Query::NoApexNS);
  1005. // We don't look into the &response, as it threw
  1006. }
  1007. TEST_F(QueryTest, delegation) {
  1008. EXPECT_NO_THROW(Query(&memory_client, Name("delegation.example.com"),
  1009. qtype, &response).process());
  1010. responseCheck(response, Rcode::NOERROR(), 0, 0, 4, 3,
  1011. NULL, delegation_txt, ns_addrs_txt);
  1012. }
  1013. TEST_F(QueryTest, secureDelegation) {
  1014. EXPECT_NO_THROW(Query(&memory_client,
  1015. Name("foo.signed-delegation.example.com"),
  1016. qtype, &response, true).process());
  1017. // Should now contain RRSIG and DS record as well.
  1018. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  1019. NULL,
  1020. (string(signed_delegation_txt) +
  1021. string(signed_delegation_ds_txt) +
  1022. string("signed-delegation.example.com. 3600 IN RRSIG ") +
  1023. getCommonRRSIGText("DS")).c_str(),
  1024. NULL);
  1025. }
  1026. TEST_F(QueryTest, secureUnsignedDelegation) {
  1027. EXPECT_NO_THROW(Query(&memory_client,
  1028. Name("foo.unsigned-delegation.example.com"),
  1029. qtype, &response, true).process());
  1030. // Should now contain RRSIG and NSEC record as well.
  1031. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  1032. NULL,
  1033. (string(unsigned_delegation_txt) +
  1034. string(unsigned_delegation_nsec_txt) +
  1035. string("unsigned-delegation.example.com. 3600 IN RRSIG ") +
  1036. getCommonRRSIGText("NSEC")).c_str(),
  1037. NULL);
  1038. }
  1039. TEST_F(QueryTest, secureUnsignedDelegationWithNSEC3) {
  1040. // Similar to the previous case, but the zone is signed with NSEC3,
  1041. // and this delegation is NOT an optout.
  1042. const Name insecurechild_name("unsigned-delegation.example.com");
  1043. mock_finder->setNSEC3Flag(true);
  1044. mock_finder->addRecord(unsigned_delegation_nsec3_txt);
  1045. Query(&memory_client, Name("foo.unsigned-delegation.example.com"),
  1046. qtype, &response, true).process();
  1047. // The response should contain the NS and matching NSEC3 with its RRSIG
  1048. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  1049. NULL,
  1050. (string(unsigned_delegation_txt) +
  1051. string(unsigned_delegation_nsec3_txt) +
  1052. mock_finder->hash_map_[insecurechild_name] +
  1053. ".example.com. 3600 IN RRSIG " +
  1054. getCommonRRSIGText("NSEC3")).c_str(),
  1055. NULL);
  1056. }
  1057. TEST_F(QueryTest, secureUnsignedDelegationWithNSEC3OptOut) {
  1058. // Similar to the previous case, but the delegation is an optout.
  1059. mock_finder->setNSEC3Flag(true);
  1060. Query(&memory_client, Name("foo.unsigned-delegation.example.com"),
  1061. qtype, &response, true).process();
  1062. // The response should contain the NS and the closest provable encloser
  1063. // proof (and their RRSIGs). The closest encloser is the apex (origin),
  1064. // and with our faked hash the covering NSEC3 for the next closer
  1065. // (= child zone name) is that for www.example.com.
  1066. responseCheck(response, Rcode::NOERROR(), 0, 0, 5, 0,
  1067. NULL,
  1068. (string(unsigned_delegation_txt) +
  1069. string(nsec3_apex_txt) +
  1070. mock_finder->hash_map_[mock_finder->getOrigin()] +
  1071. ".example.com. 3600 IN RRSIG " +
  1072. getCommonRRSIGText("NSEC3") + "\n" +
  1073. string(nsec3_www_txt) +
  1074. mock_finder->hash_map_[Name("www.example.com")] +
  1075. ".example.com. 3600 IN RRSIG " +
  1076. getCommonRRSIGText("NSEC3")).c_str(),
  1077. NULL);
  1078. }
  1079. TEST_F(QueryTest, badSecureDelegation) {
  1080. // Test whether exception is raised if DS query at delegation results in
  1081. // something different than SUCCESS or NXRRSET
  1082. EXPECT_THROW(Query(&memory_client, Name("bad-delegation.example.com"),
  1083. qtype, &response, true).process(), Query::BadDS);
  1084. // But only if DNSSEC is requested (it shouldn't even try to look for
  1085. // the DS otherwise)
  1086. EXPECT_NO_THROW(Query(&memory_client, Name("bad-delegation.example.com"),
  1087. qtype, &response).process());
  1088. }
  1089. TEST_F(QueryTest, nxdomain) {
  1090. EXPECT_NO_THROW(Query(&memory_client, Name("nxdomain.example.com"), qtype,
  1091. &response).process());
  1092. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 1, 0,
  1093. NULL, soa_txt, NULL, mock_finder->getOrigin());
  1094. }
  1095. TEST_F(QueryTest, nxdomainWithNSEC) {
  1096. // NXDOMAIN with DNSSEC proof. We should have SOA, NSEC that proves
  1097. // NXDOMAIN and NSEC that proves nonexistence of matching wildcard,
  1098. // as well as their RRSIGs.
  1099. EXPECT_NO_THROW(Query(&memory_client, Name("nxdomain.example.com"), qtype,
  1100. &response, true).process());
  1101. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  1102. NULL, (string(soa_txt) +
  1103. string("example.com. 3600 IN RRSIG ") +
  1104. getCommonRRSIGText("SOA") + "\n" +
  1105. string(nsec_nxdomain_txt) + "\n" +
  1106. string("noglue.example.com. 3600 IN RRSIG ") +
  1107. getCommonRRSIGText("NSEC") + "\n" +
  1108. string(nsec_apex_txt) + "\n" +
  1109. string("example.com. 3600 IN RRSIG ") +
  1110. getCommonRRSIGText("NSEC")).c_str(),
  1111. NULL, mock_finder->getOrigin());
  1112. }
  1113. TEST_F(QueryTest, nxdomainWithNSEC2) {
  1114. // See comments about no_txt. In this case the best possible wildcard
  1115. // is derived from the next domain of the NSEC that proves NXDOMAIN, and
  1116. // the NSEC to provide the non existence of wildcard is different from
  1117. // the first NSEC.
  1118. Query(&memory_client, Name("(.no.example.com"), qtype,
  1119. &response, true).process();
  1120. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  1121. NULL, (string(soa_txt) +
  1122. string("example.com. 3600 IN RRSIG ") +
  1123. getCommonRRSIGText("SOA") + "\n" +
  1124. string(nsec_mx_txt) + "\n" +
  1125. string("mx.example.com. 3600 IN RRSIG ") +
  1126. getCommonRRSIGText("NSEC") + "\n" +
  1127. string(nsec_no_txt) + "\n" +
  1128. string(").no.example.com. 3600 IN RRSIG ") +
  1129. getCommonRRSIGText("NSEC")).c_str(),
  1130. NULL, mock_finder->getOrigin());
  1131. }
  1132. TEST_F(QueryTest, nxdomainWithNSECDuplicate) {
  1133. // See comments about nz_txt. In this case we only need one NSEC,
  1134. // which proves both NXDOMAIN and the non existence of wildcard.
  1135. Query(&memory_client, Name("nx.no.example.com"), qtype,
  1136. &response, true).process();
  1137. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 4, 0,
  1138. NULL, (string(soa_txt) +
  1139. string("example.com. 3600 IN RRSIG ") +
  1140. getCommonRRSIGText("SOA") + "\n" +
  1141. string(nsec_no_txt) + "\n" +
  1142. string(").no.example.com. 3600 IN RRSIG ") +
  1143. getCommonRRSIGText("NSEC")).c_str(),
  1144. NULL, mock_finder->getOrigin());
  1145. }
  1146. TEST_F(QueryTest, nxdomainBadNSEC1) {
  1147. // ZoneFinder::find() returns NXDOMAIN with non NSEC RR.
  1148. mock_finder->setNSECResult(Name("badnsec.example.com"),
  1149. ZoneFinder::NXDOMAIN,
  1150. mock_finder->dname_rrset_);
  1151. EXPECT_THROW(Query(&memory_client, Name("badnsec.example.com"), qtype,
  1152. &response, true).process(),
  1153. std::bad_cast);
  1154. }
  1155. TEST_F(QueryTest, nxdomainBadNSEC2) {
  1156. // ZoneFinder::find() returns NXDOMAIN with an empty NSEC RR.
  1157. mock_finder->setNSECResult(Name("emptynsec.example.com"),
  1158. ZoneFinder::NXDOMAIN,
  1159. mock_finder->empty_nsec_rrset_);
  1160. EXPECT_THROW(Query(&memory_client, Name("emptynsec.example.com"), qtype,
  1161. &response, true).process(),
  1162. Query::BadNSEC);
  1163. }
  1164. TEST_F(QueryTest, nxdomainBadNSEC3) {
  1165. // "no-wildcard proof" returns SUCCESS. it should be NXDOMAIN.
  1166. mock_finder->setNSECResult(Name("*.example.com"),
  1167. ZoneFinder::SUCCESS,
  1168. mock_finder->dname_rrset_);
  1169. EXPECT_THROW(Query(&memory_client, Name("nxdomain.example.com"), qtype,
  1170. &response, true).process(),
  1171. Query::BadNSEC);
  1172. }
  1173. TEST_F(QueryTest, nxdomainBadNSEC4) {
  1174. // "no-wildcard proof" doesn't return RRset.
  1175. mock_finder->setNSECResult(Name("*.example.com"),
  1176. ZoneFinder::NXDOMAIN, ConstRRsetPtr());
  1177. EXPECT_THROW(Query(&memory_client, Name("nxdomain.example.com"), qtype,
  1178. &response, true).process(),
  1179. Query::BadNSEC);
  1180. }
  1181. TEST_F(QueryTest, nxdomainBadNSEC5) {
  1182. // "no-wildcard proof" returns non NSEC.
  1183. mock_finder->setNSECResult(Name("*.example.com"),
  1184. ZoneFinder::NXDOMAIN,
  1185. mock_finder->dname_rrset_);
  1186. // This is a bit odd, but we'll simply include the returned RRset.
  1187. Query(&memory_client, Name("nxdomain.example.com"), qtype,
  1188. &response, true).process();
  1189. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  1190. NULL, (string(soa_txt) +
  1191. string("example.com. 3600 IN RRSIG ") +
  1192. getCommonRRSIGText("SOA") + "\n" +
  1193. string(nsec_nxdomain_txt) + "\n" +
  1194. string("noglue.example.com. 3600 IN RRSIG ") +
  1195. getCommonRRSIGText("NSEC") + "\n" +
  1196. dname_txt + "\n" +
  1197. string("dname.example.com. 3600 IN RRSIG ") +
  1198. getCommonRRSIGText("DNAME")).c_str(),
  1199. NULL, mock_finder->getOrigin());
  1200. }
  1201. TEST_F(QueryTest, nxdomainBadNSEC6) {
  1202. // "no-wildcard proof" returns empty NSEC.
  1203. mock_finder->setNSECResult(Name("*.example.com"),
  1204. ZoneFinder::NXDOMAIN,
  1205. mock_finder->empty_nsec_rrset_);
  1206. EXPECT_THROW(Query(&memory_client, Name("nxdomain.example.com"), qtype,
  1207. &response, true).process(),
  1208. Query::BadNSEC);
  1209. }
  1210. TEST_F(QueryTest, nxrrset) {
  1211. EXPECT_NO_THROW(Query(&memory_client, Name("www.example.com"),
  1212. RRType::TXT(), &response).process());
  1213. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 1, 0,
  1214. NULL, soa_txt, NULL, mock_finder->getOrigin());
  1215. }
  1216. TEST_F(QueryTest, nxrrsetWithNSEC) {
  1217. // NXRRSET with DNSSEC proof. We should have SOA, NSEC that proves the
  1218. // NXRRSET and their RRSIGs.
  1219. Query(&memory_client, Name("www.example.com"), RRType::TXT(), &response,
  1220. true).process();
  1221. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1222. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1223. getCommonRRSIGText("SOA") + "\n" +
  1224. string(nsec_www_txt) + "\n" +
  1225. string("www.example.com. 3600 IN RRSIG ") +
  1226. getCommonRRSIGText("NSEC")).c_str(),
  1227. NULL, mock_finder->getOrigin());
  1228. }
  1229. TEST_F(QueryTest, emptyNameWithNSEC) {
  1230. // Empty non terminal with DNSSEC proof. This is one of the cases of
  1231. // Section 3.1.3.2 of RFC4035.
  1232. // mx.example.com. NSEC ).no.example.com. proves no.example.com. is a
  1233. // non empty terminal node. Note that it also implicitly proves there
  1234. // should be no closer wildcard match (because the empty name is an
  1235. // exact match), so we only need one NSEC.
  1236. // From the point of the Query::process(), this is actually no different
  1237. // from the other NXRRSET case, but we check that explicitly just in case.
  1238. Query(&memory_client, Name("no.example.com"), RRType::A(), &response,
  1239. true).process();
  1240. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1241. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1242. getCommonRRSIGText("SOA") + "\n" +
  1243. string(nsec_mx_txt) + "\n" +
  1244. string("mx.example.com. 3600 IN RRSIG ") +
  1245. getCommonRRSIGText("NSEC")).c_str(),
  1246. NULL, mock_finder->getOrigin());
  1247. }
  1248. TEST_F(QueryTest, nxrrsetWithoutNSEC) {
  1249. // NXRRSET with DNSSEC proof requested, but there's no NSEC at that node.
  1250. // This is an unexpected event (if the zone is supposed to be properly
  1251. // signed with NSECs), but we accept and ignore the oddity.
  1252. Query(&memory_client, Name("nonsec.example.com"), RRType::TXT(), &response,
  1253. true).process();
  1254. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 2, 0, NULL,
  1255. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1256. getCommonRRSIGText("SOA") + "\n").c_str(),
  1257. NULL, mock_finder->getOrigin());
  1258. }
  1259. TEST_F(QueryTest, wildcardNSEC) {
  1260. // The qname matches *.wild.example.com. The response should contain
  1261. // an NSEC that proves the non existence of a closer name.
  1262. Query(&memory_client, Name("www.wild.example.com"), RRType::A(), &response,
  1263. true).process();
  1264. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 6, 6,
  1265. (string(wild_txt).replace(0, 1, "www") +
  1266. string("www.wild.example.com. 3600 IN RRSIG ") +
  1267. getCommonRRSIGText("A") + "\n").c_str(),
  1268. (zone_ns_txt + string("example.com. 3600 IN RRSIG NS 5 "
  1269. "3 3600 20000101000000 "
  1270. "20000201000000 12345 "
  1271. "example.com. FAKEFAKEFAKE\n") +
  1272. string(nsec_wild_txt) +
  1273. string("*.wild.example.com. 3600 IN RRSIG ") +
  1274. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1275. NULL, // we are not interested in additionals in this test
  1276. mock_finder->getOrigin());
  1277. }
  1278. TEST_F(QueryTest, CNAMEwildNSEC) {
  1279. // Similar to the previous case, but the matching wildcard record is
  1280. // CNAME.
  1281. Query(&memory_client, Name("www.cnamewild.example.com"), RRType::A(),
  1282. &response, true).process();
  1283. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
  1284. (string(cnamewild_txt).replace(0, 1, "www") +
  1285. string("www.cnamewild.example.com. 3600 IN RRSIG ") +
  1286. getCommonRRSIGText("CNAME") + "\n").c_str(),
  1287. (string(nsec_cnamewild_txt) +
  1288. string("*.cnamewild.example.com. 3600 IN RRSIG ") +
  1289. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1290. NULL, // we are not interested in additionals in this test
  1291. mock_finder->getOrigin());
  1292. }
  1293. TEST_F(QueryTest, wildcardNSEC3) {
  1294. // Similar to wildcardNSEC, but the zone is signed with NSEC3.
  1295. // The next closer is y.wild.example.com, the covering NSEC3 for it
  1296. // is (in our setup) the NSEC3 for the apex.
  1297. mock_finder->setNSEC3Flag(true);
  1298. // This is NSEC3 for wild.example.com, which will be used in the middle
  1299. // of identifying the next closer name.
  1300. mock_finder->addRecord(nsec3_atwild_txt);
  1301. Query(&memory_client, Name("x.y.wild.example.com"), RRType::A(), &response,
  1302. true).process();
  1303. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 6, 6,
  1304. (string(wild_txt).replace(0, 1, "x.y") +
  1305. string("x.y.wild.example.com. 3600 IN RRSIG ") +
  1306. getCommonRRSIGText("A") + "\n").c_str(),
  1307. // 3 NSes and their RRSIG
  1308. (zone_ns_txt + string("example.com. 3600 IN RRSIG ") +
  1309. getCommonRRSIGText("NS") + "\n" +
  1310. // NSEC3 for the wildcard proof and its RRSIG
  1311. string(nsec3_apex_txt) +
  1312. mock_finder->hash_map_[Name("example.com.")] +
  1313. string(".example.com. 3600 IN RRSIG ") +
  1314. getCommonRRSIGText("NSEC3")).c_str(),
  1315. NULL, // we are not interested in additionals in this test
  1316. mock_finder->getOrigin());
  1317. }
  1318. TEST_F(QueryTest, CNAMEwildNSEC3) {
  1319. // Similar to CNAMEwildNSEC, but with NSEC3.
  1320. // The next closer is qname itself, the covering NSEC3 for it
  1321. // is (in our setup) the NSEC3 for the www.example.com.
  1322. mock_finder->setNSEC3Flag(true);
  1323. mock_finder->addRecord(nsec3_atcnamewild_txt);
  1324. Query(&memory_client, Name("www.cnamewild.example.com"), RRType::A(),
  1325. &response, true).process();
  1326. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
  1327. (string(cnamewild_txt).replace(0, 1, "www") +
  1328. string("www.cnamewild.example.com. 3600 IN RRSIG ") +
  1329. getCommonRRSIGText("CNAME") + "\n").c_str(),
  1330. (string(nsec3_www_txt) +
  1331. mock_finder->hash_map_[Name("www.example.com.")] +
  1332. string(".example.com. 3600 IN RRSIG ") +
  1333. getCommonRRSIGText("NSEC3")).c_str(),
  1334. NULL, // we are not interested in additionals in this test
  1335. mock_finder->getOrigin());
  1336. }
  1337. TEST_F(QueryTest, badWildcardNSEC3) {
  1338. // Similar to wildcardNSEC3, but emulating run time collision by
  1339. // returning NULL in the next closer proof for the closest encloser
  1340. // proof.
  1341. mock_finder->setNSEC3Flag(true);
  1342. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  1343. ConstRRsetPtr());
  1344. mock_finder->setNSEC3Result(&nsec3);
  1345. EXPECT_THROW(Query(&memory_client, Name("www.wild.example.com"),
  1346. RRType::A(), &response, true).process(),
  1347. Query::BadNSEC3);
  1348. }
  1349. TEST_F(QueryTest, badWildcardProof1) {
  1350. // Unexpected case in wildcard proof: ZoneFinder::find() returns SUCCESS
  1351. // when NXDOMAIN is expected.
  1352. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1353. ZoneFinder::SUCCESS,
  1354. mock_finder->dname_rrset_);
  1355. EXPECT_THROW(Query(&memory_client, Name("www.wild.example.com"),
  1356. RRType::A(), &response, true).process(),
  1357. Query::BadNSEC);
  1358. }
  1359. TEST_F(QueryTest, badWildcardProof2) {
  1360. // "wildcard proof" doesn't return RRset.
  1361. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1362. ZoneFinder::NXDOMAIN, ConstRRsetPtr());
  1363. EXPECT_THROW(Query(&memory_client, Name("www.wild.example.com"),
  1364. RRType::A(), &response, true).process(),
  1365. Query::BadNSEC);
  1366. }
  1367. TEST_F(QueryTest, badWildcardProof3) {
  1368. // "wildcard proof" returns empty NSEC.
  1369. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1370. ZoneFinder::NXDOMAIN,
  1371. mock_finder->empty_nsec_rrset_);
  1372. EXPECT_THROW(Query(&memory_client, Name("www.wild.example.com"),
  1373. RRType::A(), &response, true).process(),
  1374. Query::BadNSEC);
  1375. }
  1376. TEST_F(QueryTest, wildcardNxrrsetWithDuplicateNSEC) {
  1377. // NXRRSET on WILDCARD with DNSSEC proof. We should have SOA, NSEC that
  1378. // proves the NXRRSET and their RRSIGs. In this case we only need one NSEC,
  1379. // which proves both NXDOMAIN and the non existence RRSETs of wildcard.
  1380. Query(&memory_client, Name("www.wild.example.com"), RRType::TXT(), &response,
  1381. true).process();
  1382. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1383. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1384. getCommonRRSIGText("SOA") + "\n" +
  1385. string(nsec_wild_txt) +
  1386. string("*.wild.example.com. 3600 IN RRSIG ") +
  1387. getCommonRRSIGText("NSEC")+"\n").c_str(),
  1388. NULL, mock_finder->getOrigin());
  1389. }
  1390. TEST_F(QueryTest, wildcardNxrrsetWithNSEC) {
  1391. // WILDCARD + NXRRSET with DNSSEC proof. We should have SOA, NSEC that
  1392. // proves the NXRRSET and their RRSIGs. In this case we need two NSEC RRs,
  1393. // one proves NXDOMAIN and the other proves non existence RRSETs of
  1394. // wildcard.
  1395. Query(&memory_client, Name("www1.uwild.example.com"), RRType::TXT(),
  1396. &response, true).process();
  1397. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  1398. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1399. getCommonRRSIGText("SOA") + "\n" +
  1400. string(nsec_wild_txt_nxrrset) +
  1401. string("*.uwild.example.com. 3600 IN RRSIG ") +
  1402. getCommonRRSIGText("NSEC")+"\n" +
  1403. string(nsec_wild_txt_next) +
  1404. string("www.uwild.example.com. 3600 IN RRSIG ") +
  1405. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1406. NULL, mock_finder->getOrigin());
  1407. }
  1408. TEST_F(QueryTest, wildcardNxrrsetWithNSEC3) {
  1409. // Similar to the previous case, but providing NSEC3 proofs according to
  1410. // RFC5155 Section 7.2.5.
  1411. mock_finder->addRecord(nsec3_wild_txt);
  1412. mock_finder->addRecord(nsec3_uwild_txt);
  1413. mock_finder->setNSEC3Flag(true);
  1414. Query(&memory_client, Name("www1.uwild.example.com"), RRType::TXT(),
  1415. &response, true).process();
  1416. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 8, 0, NULL,
  1417. // SOA + its RRSIG
  1418. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1419. getCommonRRSIGText("SOA") + "\n" +
  1420. // NSEC3 for the closest encloser + its RRSIG
  1421. string(nsec3_uwild_txt) +
  1422. mock_finder->hash_map_[Name("uwild.example.com.")] +
  1423. ".example.com. 3600 IN RRSIG " +
  1424. getCommonRRSIGText("NSEC3") + "\n" +
  1425. // NSEC3 for the next closer + its RRSIG
  1426. string(nsec3_www_txt) +
  1427. mock_finder->hash_map_[Name("www.example.com.")] +
  1428. ".example.com. 3600 IN RRSIG " +
  1429. getCommonRRSIGText("NSEC3") + "\n" +
  1430. // NSEC3 for the wildcard + its RRSIG
  1431. string(nsec3_wild_txt) +
  1432. mock_finder->hash_map_[Name("*.uwild.example.com.")] +
  1433. ".example.com. 3600 IN RRSIG " +
  1434. getCommonRRSIGText("NSEC3")).c_str(),
  1435. NULL, mock_finder->getOrigin());
  1436. }
  1437. TEST_F(QueryTest, wildcardNxrrsetWithNSEC3Collision) {
  1438. // Similar to the previous case, but emulating run time collision by
  1439. // returning NULL in the next closer proof for the closest encloser
  1440. // proof.
  1441. mock_finder->setNSEC3Flag(true);
  1442. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  1443. ConstRRsetPtr());
  1444. mock_finder->setNSEC3Result(&nsec3);
  1445. EXPECT_THROW(Query(&memory_client, Name("www1.uwild.example.com"),
  1446. RRType::TXT(), &response, true).process(),
  1447. Query::BadNSEC3);
  1448. }
  1449. TEST_F(QueryTest, wildcardNxrrsetWithNSEC3Broken) {
  1450. // Similar to wildcardNxrrsetWithNSEC3, but no matching NSEC3 for the
  1451. // wildcard name will be returned. This shouldn't happen in a reasonably
  1452. // NSEC-signed zone, and should result in an exception.
  1453. mock_finder->setNSEC3Flag(true);
  1454. const Name wname("*.uwild.example.com.");
  1455. ZoneFinder::FindNSEC3Result nsec3(false, 0, textToRRset(nsec3_apex_txt),
  1456. ConstRRsetPtr());
  1457. mock_finder->setNSEC3Result(&nsec3, &wname);
  1458. mock_finder->addRecord(nsec3_wild_txt);
  1459. mock_finder->addRecord(nsec3_uwild_txt);
  1460. EXPECT_THROW(Query(&memory_client, Name("www1.uwild.example.com"),
  1461. RRType::TXT(), &response, true).process(),
  1462. Query::BadNSEC3);
  1463. }
  1464. TEST_F(QueryTest, wildcardEmptyWithNSEC) {
  1465. // Empty WILDCARD with DNSSEC proof. We should have SOA, NSEC that proves
  1466. // the NXDOMAIN and their RRSIGs. In this case we need two NSEC RRs,
  1467. // one proves NXDOMAIN and the other proves non existence wildcard.
  1468. Query(&memory_client, Name("a.t.example.com"), RRType::A(), &response,
  1469. true).process();
  1470. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  1471. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1472. getCommonRRSIGText("SOA") + "\n" +
  1473. string(nsec_empty_prev_txt) +
  1474. string("t.example.com. 3600 IN RRSIG ") +
  1475. getCommonRRSIGText("NSEC")+"\n" +
  1476. string(nsec_empty_txt) +
  1477. string("b.*.t.example.com. 3600 IN RRSIG ") +
  1478. getCommonRRSIGText("NSEC")+"\n").c_str(),
  1479. NULL, mock_finder->getOrigin());
  1480. }
  1481. /*
  1482. * This tests that when there's no SOA and we need a negative answer. It should
  1483. * throw in that case.
  1484. */
  1485. TEST_F(QueryTest, noSOA) {
  1486. // disable zone's SOA RR.
  1487. mock_finder->setSOAFlag(false);
  1488. // The NX Domain
  1489. EXPECT_THROW(Query(&memory_client, Name("nxdomain.example.com"),
  1490. qtype, &response).process(), Query::NoSOA);
  1491. // Of course, we don't look into the &response, as it throwed
  1492. // NXRRSET
  1493. EXPECT_THROW(Query(&memory_client, Name("nxrrset.example.com"),
  1494. qtype, &response).process(), Query::NoSOA);
  1495. }
  1496. TEST_F(QueryTest, noMatchZone) {
  1497. // there's a zone in the memory datasource but it doesn't match the qname.
  1498. // should result in REFUSED.
  1499. Query(&memory_client, Name("example.org"), qtype, &response).process();
  1500. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  1501. }
  1502. /*
  1503. * Test MX additional processing.
  1504. *
  1505. * The MX RRset has two RRs, one pointing to a known domain with
  1506. * A record, other to unknown out of zone one.
  1507. */
  1508. TEST_F(QueryTest, MX) {
  1509. Query(&memory_client, Name("mx.example.com"), RRType::MX(),
  1510. &response).process();
  1511. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 3, 3, 4,
  1512. mx_txt, NULL,
  1513. (string(ns_addrs_txt) + string(www_a_txt)).c_str());
  1514. }
  1515. /*
  1516. * Test when we ask for MX whose exchange is an alias (CNAME in this case).
  1517. *
  1518. * This should not trigger the additional processing for the exchange.
  1519. */
  1520. TEST_F(QueryTest, MXAlias) {
  1521. Query(&memory_client, Name("cnamemx.example.com"), RRType::MX(),
  1522. &response).process();
  1523. // there shouldn't be no additional RRs for the exchanges (we have 3
  1524. // RRs for the NS). The normal MX case is tested separately so we don't
  1525. // bother to examine the answer (and authority) sections.
  1526. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1527. NULL, NULL, ns_addrs_txt);
  1528. }
  1529. /*
  1530. * Tests encountering a cname.
  1531. *
  1532. * There are tests leading to successful answers, NXRRSET, NXDOMAIN and
  1533. * out of the zone.
  1534. *
  1535. * TODO: We currently don't do chaining, so only the CNAME itself should be
  1536. * returned.
  1537. */
  1538. TEST_F(QueryTest, CNAME) {
  1539. Query(&memory_client, Name("cname.example.com"), RRType::A(),
  1540. &response).process();
  1541. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1542. cname_txt, NULL, NULL);
  1543. }
  1544. TEST_F(QueryTest, explicitCNAME) {
  1545. // same owner name as the CNAME test but explicitly query for CNAME RR.
  1546. // expect the same response as we don't provide a full chain yet.
  1547. Query(&memory_client, Name("cname.example.com"), RRType::CNAME(),
  1548. &response).process();
  1549. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1550. cname_txt, zone_ns_txt, ns_addrs_txt);
  1551. }
  1552. TEST_F(QueryTest, CNAME_NX_RRSET) {
  1553. // Leads to www.example.com, it doesn't have TXT
  1554. // note: with chaining, what should be expected is not trivial:
  1555. // BIND 9 returns the CNAME in answer and SOA in authority, no additional.
  1556. // NSD returns the CNAME, NS in authority, A/AAAA for NS in additional.
  1557. Query(&memory_client, Name("cname.example.com"), RRType::TXT(),
  1558. &response).process();
  1559. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1560. cname_txt, NULL, NULL);
  1561. }
  1562. TEST_F(QueryTest, explicitCNAME_NX_RRSET) {
  1563. // same owner name as the NXRRSET test but explicitly query for CNAME RR.
  1564. Query(&memory_client, Name("cname.example.com"), RRType::CNAME(),
  1565. &response).process();
  1566. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1567. cname_txt, zone_ns_txt, ns_addrs_txt);
  1568. }
  1569. TEST_F(QueryTest, CNAME_NX_DOMAIN) {
  1570. // Leads to nxdomain.example.com
  1571. // note: with chaining, what should be expected is not trivial:
  1572. // BIND 9 returns the CNAME in answer and SOA in authority, no additional,
  1573. // RCODE being NXDOMAIN.
  1574. // NSD returns the CNAME, NS in authority, A/AAAA for NS in additional,
  1575. // RCODE being NOERROR.
  1576. Query(&memory_client, Name("cnamenxdom.example.com"), RRType::A(),
  1577. &response).process();
  1578. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1579. cname_nxdom_txt, NULL, NULL);
  1580. }
  1581. TEST_F(QueryTest, explicitCNAME_NX_DOMAIN) {
  1582. // same owner name as the NXDOMAIN test but explicitly query for CNAME RR.
  1583. Query(&memory_client, Name("cnamenxdom.example.com"), RRType::CNAME(),
  1584. &response).process();
  1585. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1586. cname_nxdom_txt, zone_ns_txt, ns_addrs_txt);
  1587. }
  1588. TEST_F(QueryTest, CNAME_OUT) {
  1589. /*
  1590. * This leads out of zone. This should have only the CNAME even
  1591. * when we do chaining.
  1592. *
  1593. * TODO: We should be able to have two zones in the mock data source.
  1594. * Then the same test should be done with .org included there and
  1595. * see what it does (depends on what we want to do)
  1596. */
  1597. Query(&memory_client, Name("cnameout.example.com"), RRType::A(),
  1598. &response).process();
  1599. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1600. cname_out_txt, NULL, NULL);
  1601. }
  1602. TEST_F(QueryTest, explicitCNAME_OUT) {
  1603. // same owner name as the OUT test but explicitly query for CNAME RR.
  1604. Query(&memory_client, Name("cnameout.example.com"), RRType::CNAME(),
  1605. &response).process();
  1606. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1607. cname_out_txt, zone_ns_txt, ns_addrs_txt);
  1608. }
  1609. /*
  1610. * Test a query under a domain with DNAME. We should get a synthetized CNAME
  1611. * as well as the DNAME.
  1612. *
  1613. * TODO: Once we have CNAME chaining, check it works with synthetized CNAMEs
  1614. * as well. This includes tests pointing inside the zone, outside the zone,
  1615. * pointing to NXRRSET and NXDOMAIN cases (similarly as with CNAME).
  1616. */
  1617. TEST_F(QueryTest, DNAME) {
  1618. Query(&memory_client, Name("www.dname.example.com"), RRType::A(),
  1619. &response).process();
  1620. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1621. (string(dname_txt) + synthetized_cname_txt).c_str(),
  1622. NULL, NULL);
  1623. }
  1624. /*
  1625. * Ask an ANY query below a DNAME. Should return the DNAME and synthetized
  1626. * CNAME.
  1627. *
  1628. * ANY is handled specially sometimes. We check it is not the case with
  1629. * DNAME.
  1630. */
  1631. TEST_F(QueryTest, DNAME_ANY) {
  1632. Query(&memory_client, Name("www.dname.example.com"), RRType::ANY(),
  1633. &response).process();
  1634. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1635. (string(dname_txt) + synthetized_cname_txt).c_str(), NULL, NULL);
  1636. }
  1637. // Test when we ask for DNAME explicitly, it does no synthetizing.
  1638. TEST_F(QueryTest, explicitDNAME) {
  1639. Query(&memory_client, Name("dname.example.com"), RRType::DNAME(),
  1640. &response).process();
  1641. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1642. dname_txt, zone_ns_txt, ns_addrs_txt);
  1643. }
  1644. /*
  1645. * Request a RRset at the domain with DNAME. It should not synthetize
  1646. * the CNAME, it should return the RRset.
  1647. */
  1648. TEST_F(QueryTest, DNAME_A) {
  1649. Query(&memory_client, Name("dname.example.com"), RRType::A(),
  1650. &response).process();
  1651. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1652. dname_a_txt, zone_ns_txt, ns_addrs_txt);
  1653. }
  1654. /*
  1655. * Request a RRset at the domain with DNAME that is not there (NXRRSET).
  1656. * It should not synthetize the CNAME.
  1657. */
  1658. TEST_F(QueryTest, DNAME_NX_RRSET) {
  1659. EXPECT_NO_THROW(Query(&memory_client, Name("dname.example.com"),
  1660. RRType::TXT(), &response).process());
  1661. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 1, 0,
  1662. NULL, soa_txt, NULL, mock_finder->getOrigin());
  1663. }
  1664. /*
  1665. * Constructing the CNAME will result in a name that is too long. This,
  1666. * however, should not throw (and crash the server), but respond with
  1667. * YXDOMAIN.
  1668. */
  1669. TEST_F(QueryTest, LongDNAME) {
  1670. // A name that is as long as it can be
  1671. Name longname(
  1672. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1673. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1674. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1675. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1676. "dname.example.com.");
  1677. EXPECT_NO_THROW(Query(&memory_client, longname, RRType::A(),
  1678. &response).process());
  1679. responseCheck(response, Rcode::YXDOMAIN(), AA_FLAG, 1, 0, 0,
  1680. dname_txt, NULL, NULL);
  1681. }
  1682. /*
  1683. * Constructing the CNAME will result in a name of maximal length.
  1684. * This tests that we don't reject valid one by some kind of off by
  1685. * one mistake.
  1686. */
  1687. TEST_F(QueryTest, MaxLenDNAME) {
  1688. Name longname(
  1689. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1690. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1691. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1692. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1693. "dname.example.com.");
  1694. EXPECT_NO_THROW(Query(&memory_client, longname, RRType::A(),
  1695. &response).process());
  1696. // Check the answer is OK
  1697. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1698. NULL, NULL, NULL);
  1699. // Check that the CNAME has the maximal length.
  1700. bool ok(false);
  1701. for (RRsetIterator i(response.beginSection(Message::SECTION_ANSWER));
  1702. i != response.endSection(Message::SECTION_ANSWER); ++ i) {
  1703. if ((*i)->getType() == RRType::CNAME()) {
  1704. ok = true;
  1705. RdataIteratorPtr ci((*i)->getRdataIterator());
  1706. ASSERT_FALSE(ci->isLast()) << "The CNAME is empty";
  1707. /*
  1708. * Does anybody have a clue why, if the Name::MAX_WIRE is put
  1709. * directly inside ASSERT_EQ, it fails to link and complains
  1710. * it is unresolved external?
  1711. */
  1712. const size_t max_len(Name::MAX_WIRE);
  1713. ASSERT_EQ(max_len, dynamic_cast<const rdata::generic::CNAME&>(
  1714. ci->getCurrent()).getCname().getLength());
  1715. }
  1716. }
  1717. EXPECT_TRUE(ok) << "The synthetized CNAME not found";
  1718. }
  1719. // Test for this test module itself
  1720. void
  1721. nsec3Check(bool expected_matched, uint8_t expected_labels,
  1722. const string& expected_rrsets_txt,
  1723. const ZoneFinder::FindNSEC3Result& result)
  1724. {
  1725. vector<ConstRRsetPtr> actual_rrsets;
  1726. EXPECT_EQ(expected_matched, result.matched);
  1727. // Convert to int so the error messages would be more readable:
  1728. EXPECT_EQ(static_cast<int>(expected_labels),
  1729. static_cast<int>(result.closest_labels));
  1730. if (result.closest_proof) {
  1731. actual_rrsets.push_back(result.closest_proof);
  1732. }
  1733. if (result.next_proof) {
  1734. actual_rrsets.push_back(result.next_proof);
  1735. }
  1736. rrsetsCheck(expected_rrsets_txt, actual_rrsets.begin(),
  1737. actual_rrsets.end());
  1738. }
  1739. TEST_F(QueryTest, findNSEC3) {
  1740. // In all test cases in the recursive mode, the closest encloser is the
  1741. // apex, and result's closest_labels should be the number of apex labels.
  1742. // (In non recursive mode closest_labels should be the # labels of the
  1743. // query name)
  1744. const uint8_t expected_closest_labels =
  1745. Name("example.com").getLabelCount();
  1746. // Apex name. It should have a matching NSEC3
  1747. {
  1748. SCOPED_TRACE("apex, non recursive");
  1749. nsec3Check(true, expected_closest_labels, nsec3_apex_txt,
  1750. mock_finder->findNSEC3(Name("example.com"), false));
  1751. }
  1752. // Recursive mode doesn't change the result in this case.
  1753. {
  1754. SCOPED_TRACE("apex, recursive");
  1755. nsec3Check(true, expected_closest_labels, nsec3_apex_txt,
  1756. mock_finder->findNSEC3(Name("example.com"), true));
  1757. }
  1758. // Non existent name. Disabling recursion, a covering NSEC3 should be
  1759. // returned.
  1760. {
  1761. SCOPED_TRACE("nxdomain, non recursive");
  1762. nsec3Check(false, 4, nsec3_www_txt,
  1763. mock_finder->findNSEC3(Name("nxdomain.example.com"),
  1764. false));
  1765. }
  1766. // Non existent name. The closest provable encloser is the apex,
  1767. // and next closer is the query name.
  1768. {
  1769. SCOPED_TRACE("nxdomain, recursive");
  1770. nsec3Check(true, expected_closest_labels,
  1771. string(nsec3_apex_txt) + string(nsec3_www_txt),
  1772. mock_finder->findNSEC3(Name("nxdomain.example.com"), true));
  1773. }
  1774. // Similar to the previous case, but next closer name is different
  1775. // (is the parent) of the non existent name.
  1776. {
  1777. SCOPED_TRACE("nxdomain, next closer != qname");
  1778. nsec3Check(true, expected_closest_labels,
  1779. string(nsec3_apex_txt) + string(nsec3_www_txt),
  1780. mock_finder->findNSEC3(Name("nx.domain.example.com"),
  1781. true));
  1782. }
  1783. // In the rest of test we check hash comparison for wrap around cases.
  1784. {
  1785. SCOPED_TRACE("largest");
  1786. nsec3Check(false, 4, nsec3_apex_txt,
  1787. mock_finder->findNSEC3(Name("nxdomain2.example.com"),
  1788. false));
  1789. }
  1790. {
  1791. SCOPED_TRACE("smallest");
  1792. nsec3Check(false, 4, nsec3_www_txt,
  1793. mock_finder->findNSEC3(Name("nxdomain3.example.com"),
  1794. false));
  1795. }
  1796. }
  1797. // This tests that the DS is returned above the delegation point as
  1798. // an authoritative answer, not a delegation. This is as described in
  1799. // RFC 4035, section 3.1.4.1.
  1800. // This mock finder is used for some DS-query tests to support the cases
  1801. // where the query is expected to be handled in a different zone than our
  1802. // main test zone, example.com. Only limited methods are expected to called
  1803. // (and for limited purposes) on this class object in these tests, which
  1804. // are overridden below.
  1805. class AlternateZoneFinder : public MockZoneFinder {
  1806. public:
  1807. // This zone is expected not to have a DS by default and return NXRRSET
  1808. // for a DS query. If have_ds is set to true on construction, it will
  1809. // return a faked DS answer.
  1810. AlternateZoneFinder(const Name& origin, bool have_ds = false) :
  1811. MockZoneFinder(), origin_(origin), have_ds_(have_ds)
  1812. {}
  1813. virtual isc::dns::Name getOrigin() const { return (origin_); }
  1814. virtual ZoneFinderContextPtr find(const isc::dns::Name&,
  1815. const isc::dns::RRType& type,
  1816. const FindOptions options)
  1817. {
  1818. if (type == RRType::SOA()) {
  1819. RRsetPtr soa = textToRRset(origin_.toText() + " 3600 IN SOA . . "
  1820. "0 0 0 0 0\n", origin_);
  1821. soa->addRRsig(RdataPtr(new generic::RRSIG(
  1822. getCommonRRSIGText("SOA"))));
  1823. return (createContext(options, SUCCESS, soa));
  1824. }
  1825. if (type == RRType::NS()) {
  1826. RRsetPtr ns = textToRRset(origin_.toText() + " 3600 IN NS " +
  1827. Name("ns").concatenate(origin_).toText());
  1828. ns->addRRsig(RdataPtr(new generic::RRSIG(
  1829. getCommonRRSIGText("NS"))));
  1830. return (createContext(options, SUCCESS, ns));
  1831. }
  1832. if (type == RRType::DS()) {
  1833. if (have_ds_) {
  1834. RRsetPtr ds = textToRRset(origin_.toText() +
  1835. " 3600 IN DS 57855 5 1 " +
  1836. "49FD46E6C4B45C55D4AC69CBD"
  1837. "3CD34AC1AFE51DE");
  1838. ds->addRRsig(RdataPtr(new generic::RRSIG(
  1839. getCommonRRSIGText("DS"))));
  1840. return (createContext(options, SUCCESS, ds));
  1841. } else {
  1842. RRsetPtr nsec = textToRRset(origin_.toText() +
  1843. " 3600 IN NSEC " +
  1844. origin_.toText() +
  1845. " SOA NSEC RRSIG");
  1846. nsec->addRRsig(RdataPtr(new generic::RRSIG(
  1847. getCommonRRSIGText("NSEC"))));
  1848. return (createContext(options, NXRRSET, nsec,
  1849. RESULT_NSEC_SIGNED));
  1850. }
  1851. }
  1852. // Returning NXDOMAIN is not correct, but doesn't matter for our tests.
  1853. return (createContext(options, NXDOMAIN, ConstRRsetPtr()));
  1854. }
  1855. private:
  1856. const Name origin_;
  1857. const bool have_ds_;
  1858. };
  1859. TEST_F(QueryTest, dsAboveDelegation) {
  1860. // Pretending to have authority for the child zone, too.
  1861. memory_client.addZone(ZoneFinderPtr(new AlternateZoneFinder(
  1862. Name("delegation.example.com"))));
  1863. // The following will succeed only if the search goes to the parent
  1864. // zone, not the child one we added above.
  1865. EXPECT_NO_THROW(Query(&memory_client, Name("delegation.example.com"),
  1866. RRType::DS(), &response, true).process());
  1867. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 4, 6,
  1868. (string(delegation_ds_txt) + "\n" +
  1869. "delegation.example.com. 3600 IN RRSIG " +
  1870. getCommonRRSIGText("DS")).c_str(),
  1871. (string(zone_ns_txt) + "\n" +
  1872. "example.com. 3600 IN RRSIG " +
  1873. getCommonRRSIGText("NS")).c_str(),
  1874. ns_addrs_and_sig_txt.c_str());
  1875. }
  1876. TEST_F(QueryTest, dsAboveDelegationNoData) {
  1877. // Similar to the previous case, but the query is for an unsigned zone
  1878. // (which doesn't have a DS at the parent). The response should be a
  1879. // "no data" error. The query should still be handled at the parent.
  1880. memory_client.addZone(ZoneFinderPtr(
  1881. new AlternateZoneFinder(
  1882. Name("unsigned-delegation.example.com"))));
  1883. // The following will succeed only if the search goes to the parent
  1884. // zone, not the child one we added above.
  1885. EXPECT_NO_THROW(Query(&memory_client,
  1886. Name("unsigned-delegation.example.com"),
  1887. RRType::DS(), &response, true).process());
  1888. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1889. (string(soa_txt) +
  1890. string("example.com. 3600 IN RRSIG ") +
  1891. getCommonRRSIGText("SOA") + "\n" +
  1892. string(unsigned_delegation_nsec_txt) +
  1893. "unsigned-delegation.example.com. 3600 IN RRSIG " +
  1894. getCommonRRSIGText("NSEC")).c_str(),
  1895. NULL, mock_finder->getOrigin());
  1896. }
  1897. // This one checks that type-DS query results in a "no data" response
  1898. // when it happens to be sent to the child zone, as described in RFC 4035,
  1899. // section 3.1.4.1. The example is inspired by the B.8. example from the RFC.
  1900. TEST_F(QueryTest, dsBelowDelegation) {
  1901. EXPECT_NO_THROW(Query(&memory_client, Name("example.com"),
  1902. RRType::DS(), &response, true).process());
  1903. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1904. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1905. getCommonRRSIGText("SOA") + "\n" +
  1906. string(nsec_apex_txt) + "\n" +
  1907. string("example.com. 3600 IN RRSIG ") +
  1908. getCommonRRSIGText("NSEC")).c_str(), NULL,
  1909. mock_finder->getOrigin());
  1910. }
  1911. // Similar to the previous case, but even more pathological: the DS somehow
  1912. // exists in the child zone. The Query module should still return SOA.
  1913. // In our implementation NSEC/NSEC3 isn't attached in this case.
  1914. TEST_F(QueryTest, dsBelowDelegationWithDS) {
  1915. mock_finder->addRecord(zone_ds_txt); // add the DS to the child's apex
  1916. EXPECT_NO_THROW(Query(&memory_client, Name("example.com"),
  1917. RRType::DS(), &response, true).process());
  1918. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 2, 0, NULL,
  1919. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1920. getCommonRRSIGText("SOA")).c_str(), NULL,
  1921. mock_finder->getOrigin());
  1922. }
  1923. // DS query received at a completely irrelevant (neither parent nor child)
  1924. // server. It should just like the "noZone" test case, but DS query involves
  1925. // special processing, so we test it explicitly.
  1926. TEST_F(QueryTest, dsNoZone) {
  1927. Query(&memory_client, Name("example"), RRType::DS(), &response,
  1928. true).process();
  1929. responseCheck(response, Rcode::REFUSED(), 0, 0, 0, 0, NULL, NULL, NULL);
  1930. }
  1931. // DS query for a "grandchild" zone. This should result in normal
  1932. // delegation (unless this server also has authority of the grandchild zone).
  1933. TEST_F(QueryTest, dsAtGrandParent) {
  1934. Query(&memory_client, Name("grand.delegation.example.com"), RRType::DS(),
  1935. &response, true).process();
  1936. responseCheck(response, Rcode::NOERROR(), 0, 0, 6, 6, NULL,
  1937. (string(delegation_txt) + string(delegation_ds_txt) +
  1938. "delegation.example.com. 3600 IN RRSIG " +
  1939. getCommonRRSIGText("DS")).c_str(),
  1940. ns_addrs_and_sig_txt.c_str());
  1941. }
  1942. // DS query sent to a "grandparent" server that also has authority for the
  1943. // child zone. In this case the query should be handled in the child
  1944. // side and should result in no data with SOA. Note that the server doesn't
  1945. // have authority for the "parent". Unlike the dsAboveDelegation test case
  1946. // the query should be handled in the child zone, not in the grandparent.
  1947. TEST_F(QueryTest, dsAtGrandParentAndChild) {
  1948. // Pretending to have authority for the child zone, too.
  1949. const Name childname("grand.delegation.example.com");
  1950. memory_client.addZone(ZoneFinderPtr(
  1951. new AlternateZoneFinder(childname)));
  1952. Query(&memory_client, childname, RRType::DS(), &response, true).process();
  1953. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1954. (childname.toText() + " 3600 IN SOA . . 0 0 0 0 0\n" +
  1955. childname.toText() + " 3600 IN RRSIG " +
  1956. getCommonRRSIGText("SOA") + "\n" +
  1957. childname.toText() + " 3600 IN NSEC " +
  1958. childname.toText() + " SOA NSEC RRSIG\n" +
  1959. childname.toText() + " 3600 IN RRSIG " +
  1960. getCommonRRSIGText("NSEC")).c_str(), NULL, childname);
  1961. }
  1962. // DS query for the root name (quite pathological). Since there's no "parent",
  1963. // the query will be handled in the root zone anyway, and should (normally)
  1964. // result in no data.
  1965. TEST_F(QueryTest, dsAtRoot) {
  1966. // Pretend to be a root server.
  1967. memory_client.addZone(ZoneFinderPtr(
  1968. new AlternateZoneFinder(Name::ROOT_NAME())));
  1969. Query(&memory_client, Name::ROOT_NAME(), RRType::DS(), &response,
  1970. true).process();
  1971. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1972. (string(". 3600 IN SOA . . 0 0 0 0 0\n") +
  1973. ". 3600 IN RRSIG " + getCommonRRSIGText("SOA") + "\n" +
  1974. ". 3600 IN NSEC " + ". SOA NSEC RRSIG\n" +
  1975. ". 3600 IN RRSIG " +
  1976. getCommonRRSIGText("NSEC")).c_str(), NULL);
  1977. }
  1978. // Even more pathological case: A faked root zone actually has its own DS
  1979. // query. How we respond wouldn't matter much in practice, but check if
  1980. // it behaves as it's intended. This implementation should return the DS.
  1981. TEST_F(QueryTest, dsAtRootWithDS) {
  1982. memory_client.addZone(ZoneFinderPtr(
  1983. new AlternateZoneFinder(Name::ROOT_NAME(),
  1984. true)));
  1985. Query(&memory_client, Name::ROOT_NAME(), RRType::DS(), &response,
  1986. true).process();
  1987. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
  1988. (string(". 3600 IN DS 57855 5 1 49FD46E6C4B45C55D4AC69CBD"
  1989. "3CD34AC1AFE51DE\n") +
  1990. ". 3600 IN RRSIG " + getCommonRRSIGText("DS")).c_str(),
  1991. (string(". 3600 IN NS ns.\n") +
  1992. ". 3600 IN RRSIG " + getCommonRRSIGText("NS")).c_str(),
  1993. NULL);
  1994. }
  1995. // Check the signature is present when an NXRRSET is returned
  1996. TEST_F(QueryTest, nxrrsetWithNSEC3) {
  1997. mock_finder->setNSEC3Flag(true);
  1998. // NXRRSET with DNSSEC proof. We should have SOA, NSEC3 that proves the
  1999. // NXRRSET and their RRSIGs.
  2000. Query(&memory_client, Name("www.example.com"), RRType::TXT(), &response,
  2001. true).process();
  2002. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2003. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  2004. getCommonRRSIGText("SOA") + "\n" +
  2005. string(nsec3_www_txt) + "\n" +
  2006. mock_finder->hash_map_[Name("www.example.com.")] +
  2007. ".example.com. 3600 IN RRSIG " +
  2008. getCommonRRSIGText("NSEC3") + "\n").c_str(),
  2009. NULL, mock_finder->getOrigin());
  2010. }
  2011. // Check the exception is correctly raised when the NSEC3 thing isn't in the
  2012. // zone
  2013. TEST_F(QueryTest, nxrrsetMissingNSEC3) {
  2014. mock_finder->setNSEC3Flag(true);
  2015. // We just need it to return false for "matched". This indicates
  2016. // there's no exact match for NSEC3 on www.example.com.
  2017. ZoneFinder::FindNSEC3Result nsec3(false, 0, ConstRRsetPtr(),
  2018. ConstRRsetPtr());
  2019. mock_finder->setNSEC3Result(&nsec3);
  2020. EXPECT_THROW(Query(&memory_client, Name("www.example.com"), RRType::TXT(),
  2021. &response, true).process(), Query::BadNSEC3);
  2022. }
  2023. TEST_F(QueryTest, nxrrsetWithNSEC3_ds_exact) {
  2024. mock_finder->addRecord(unsigned_delegation_nsec3_txt);
  2025. mock_finder->setNSEC3Flag(true);
  2026. // This delegation has no DS, but does have a matching NSEC3 record
  2027. // (See RFC5155 section 7.2.4)
  2028. Query(&memory_client, Name("unsigned-delegation.example.com."),
  2029. RRType::DS(), &response, true).process();
  2030. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2031. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  2032. getCommonRRSIGText("SOA") + "\n" +
  2033. string(unsigned_delegation_nsec3_txt) + "\n" +
  2034. mock_finder->
  2035. hash_map_[Name("unsigned-delegation.example.com.")] +
  2036. ".example.com. 3600 IN RRSIG " +
  2037. getCommonRRSIGText("NSEC3") + "\n").c_str(),
  2038. NULL, mock_finder->getOrigin());
  2039. }
  2040. TEST_F(QueryTest, nxrrsetWithNSEC3_ds_no_exact) {
  2041. mock_finder->addRecord(unsigned_delegation_nsec3_txt);
  2042. mock_finder->setNSEC3Flag(true);
  2043. // This delegation has no DS, and no directly matching NSEC3 record
  2044. // So the response should contain closest encloser proof (and the
  2045. // 'next closer' should have opt-out set, though that is not
  2046. // actually checked)
  2047. // (See RFC5155 section 7.2.4)
  2048. Query(&memory_client, Name("unsigned-delegation-optout.example.com."),
  2049. RRType::DS(), &response, true).process();
  2050. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  2051. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  2052. getCommonRRSIGText("SOA") + "\n" +
  2053. string(nsec3_apex_txt) + "\n" +
  2054. mock_finder->hash_map_[Name("example.com.")] +
  2055. ".example.com. 3600 IN RRSIG " +
  2056. getCommonRRSIGText("NSEC3") + "\n" +
  2057. string(unsigned_delegation_nsec3_txt) + "\n" +
  2058. mock_finder->
  2059. hash_map_[Name("unsigned-delegation.example.com.")] +
  2060. ".example.com. 3600 IN RRSIG " +
  2061. getCommonRRSIGText("NSEC3") + "\n").c_str(),
  2062. NULL, mock_finder->getOrigin());
  2063. }
  2064. TEST_F(QueryTest, nxdomainWithNSEC3Proof) {
  2065. // Name Error (NXDOMAIN) case with NSEC3 proof per RFC5155 Section 7.2.2.
  2066. // Enable NSEC3
  2067. mock_finder->setNSEC3Flag(true);
  2068. // This will be the covering NSEC3 for the next closer
  2069. mock_finder->addRecord(nsec3_uwild_txt);
  2070. // This will be the covering NSEC3 for the possible wildcard
  2071. mock_finder->addRecord(unsigned_delegation_nsec3_txt);
  2072. Query(&memory_client, Name("nxdomain.example.com"), qtype,
  2073. &response, true).process();
  2074. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 8, 0, NULL,
  2075. // SOA + its RRSIG
  2076. (string(soa_txt) +
  2077. string("example.com. 3600 IN RRSIG ") +
  2078. getCommonRRSIGText("SOA") + "\n" +
  2079. // NSEC3 for the closest encloser + its RRSIG
  2080. string(nsec3_apex_txt) + "\n" +
  2081. mock_finder->hash_map_[mock_finder->getOrigin()] +
  2082. string(".example.com. 3600 IN RRSIG ") +
  2083. getCommonRRSIGText("NSEC3") + "\n" +
  2084. // NSEC3 for the next closer + its RRSIG
  2085. string(nsec3_uwild_txt) + "\n" +
  2086. mock_finder->hash_map_[Name("uwild.example.com")] +
  2087. ".example.com. 3600 IN RRSIG " +
  2088. getCommonRRSIGText("NSEC3") + "\n" +
  2089. // NSEC3 for the wildcard + its RRSIG
  2090. string(unsigned_delegation_nsec3_txt) +
  2091. mock_finder->hash_map_[
  2092. Name("unsigned-delegation.example.com")] +
  2093. ".example.com. 3600 IN RRSIG " +
  2094. getCommonRRSIGText("NSEC3")).c_str(),
  2095. NULL, mock_finder->getOrigin());
  2096. }
  2097. TEST_F(QueryTest, nxdomainWithBadNextNSEC3Proof) {
  2098. // Similar to the previous case, but emulating run time collision by
  2099. // returning NULL in the next closer proof for the closest encloser
  2100. // proof.
  2101. mock_finder->setNSEC3Flag(true);
  2102. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  2103. ConstRRsetPtr());
  2104. mock_finder->setNSEC3Result(&nsec3);
  2105. EXPECT_THROW(Query(&memory_client, Name("nxdomain.example.com"),
  2106. RRType::TXT(), &response, true).process(),
  2107. Query::BadNSEC3);
  2108. }
  2109. TEST_F(QueryTest, nxdomainWithBadWildcardNSEC3Proof) {
  2110. // Similar to nxdomainWithNSEC3Proof, but let findNSEC3() return a matching
  2111. // NSEC3 for the possible wildcard name, emulating run-time collision.
  2112. // This should result in BadNSEC3 exception.
  2113. mock_finder->setNSEC3Flag(true);
  2114. mock_finder->addRecord(nsec3_uwild_txt);
  2115. mock_finder->addRecord(unsigned_delegation_nsec3_txt);
  2116. const Name wname("*.example.com");
  2117. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  2118. ConstRRsetPtr());
  2119. mock_finder->setNSEC3Result(&nsec3, &wname);
  2120. EXPECT_THROW(Query(&memory_client, Name("nxdomain.example.com"), qtype,
  2121. &response, true).process(),
  2122. Query::BadNSEC3);
  2123. }
  2124. // The following are tentative tests until we really add tests for the
  2125. // query logic for these cases. At that point it's probably better to
  2126. // clean them up.
  2127. TEST_F(QueryTest, emptyNameWithNSEC3) {
  2128. mock_finder->setNSEC3Flag(true);
  2129. ZoneFinderContextPtr result = mock_finder->find(
  2130. Name("no.example.com"), RRType::A(), ZoneFinder::FIND_DNSSEC);
  2131. EXPECT_EQ(ZoneFinder::NXRRSET, result->code);
  2132. EXPECT_FALSE(result->rrset);
  2133. EXPECT_TRUE(result->isNSEC3Signed());
  2134. EXPECT_FALSE(result->isWildcard());
  2135. }
  2136. }