query_unittest.cc 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740
  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. const char* const soa_txt = "example.com. 3600 IN SOA . . 0 0 0 0 0\n";
  45. const char* const zone_ns_txt =
  46. "example.com. 3600 IN NS glue.delegation.example.com.\n"
  47. "example.com. 3600 IN NS noglue.example.com.\n"
  48. "example.com. 3600 IN NS example.net.\n";
  49. const char* const ns_addrs_txt =
  50. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  51. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n"
  52. "noglue.example.com. 3600 IN A 192.0.2.53\n";
  53. const char* const delegation_txt =
  54. "delegation.example.com. 3600 IN NS glue.delegation.example.com.\n"
  55. "delegation.example.com. 3600 IN NS noglue.example.com.\n"
  56. "delegation.example.com. 3600 IN NS cname.example.com.\n"
  57. "delegation.example.com. 3600 IN NS example.org.\n";
  58. const char* const mx_txt =
  59. "mx.example.com. 3600 IN MX 10 www.example.com.\n"
  60. "mx.example.com. 3600 IN MX 20 mailer.example.org.\n"
  61. "mx.example.com. 3600 IN MX 30 mx.delegation.example.com.\n";
  62. const char* const www_a_txt = "www.example.com. 3600 IN A 192.0.2.80\n";
  63. const char* const cname_txt =
  64. "cname.example.com. 3600 IN CNAME www.example.com.\n";
  65. const char* const cname_nxdom_txt =
  66. "cnamenxdom.example.com. 3600 IN CNAME nxdomain.example.com.\n";
  67. // CNAME Leading out of zone
  68. const char* const cname_out_txt =
  69. "cnameout.example.com. 3600 IN CNAME www.example.org.\n";
  70. // The DNAME to do tests against
  71. const char* const dname_txt =
  72. "dname.example.com. 3600 IN DNAME "
  73. "somethinglong.dnametarget.example.com.\n";
  74. // Some data at the dname node (allowed by RFC 2672)
  75. const char* const dname_a_txt =
  76. "dname.example.com. 3600 IN A 192.0.2.5\n";
  77. // This is not inside the zone, this is created at runtime
  78. const char* const synthetized_cname_txt =
  79. "www.dname.example.com. 3600 IN CNAME "
  80. "www.somethinglong.dnametarget.example.com.\n";
  81. // The rest of data won't be referenced from the test cases.
  82. const char* const other_zone_rrs =
  83. "cnamemailer.example.com. 3600 IN CNAME www.example.com.\n"
  84. "cnamemx.example.com. 3600 IN MX 10 cnamemailer.example.com.\n"
  85. "mx.delegation.example.com. 3600 IN A 192.0.2.100\n";
  86. // Wildcards
  87. const char* const wild_txt = "*.wild.example.com. 3600 IN A 192.0.2.7\n";
  88. const char* const nsec_wild_txt =
  89. "*.wild.example.com. 3600 IN NSEC www.example.com. A NSEC RRSIG\n";
  90. const char* const cnamewild_txt =
  91. "*.cnamewild.example.com. 3600 IN CNAME www.example.org.\n";
  92. const char* const nsec_cnamewild_txt = "*.cnamewild.example.com. "
  93. "3600 IN NSEC delegation.example.com. CNAME NSEC RRSIG\n";
  94. // Wildcard_nxrrset
  95. const char* const wild_txt_nxrrset =
  96. "*.uwild.example.com. 3600 IN A 192.0.2.9\n";
  97. const char* const nsec_wild_txt_nxrrset =
  98. "*.uwild.example.com. 3600 IN NSEC www.uwild.example.com. A NSEC RRSIG\n";
  99. const char* const wild_txt_next =
  100. "www.uwild.example.com. 3600 IN A 192.0.2.11\n";
  101. const char* const nsec_wild_txt_next =
  102. "www.uwild.example.com. 3600 IN NSEC *.wild.example.com. A NSEC RRSIG\n";
  103. // Wildcard empty
  104. const char* const empty_txt = "b.*.t.example.com. 3600 IN A 192.0.2.13\n";
  105. const char* const nsec_empty_txt =
  106. "b.*.t.example.com. 3600 IN NSEC *.uwild.example.com. A NSEC RRSIG\n";
  107. const char* const empty_prev_txt = "t.example.com. 3600 IN A 192.0.2.15\n";
  108. const char* const nsec_empty_prev_txt =
  109. "t.example.com. 3600 IN NSEC b.*.t.example.com. A NSEC RRSIG\n";
  110. // Used in NXDOMAIN proof test. We are going to test some unusual case where
  111. // the best possible wildcard is below the "next domain" of the NSEC RR that
  112. // proves the NXDOMAIN, i.e.,
  113. // mx.example.com. (exist)
  114. // (.no.example.com. (qname, NXDOMAIN)
  115. // ).no.example.com. (exist)
  116. // *.no.example.com. (best possible wildcard, not exist)
  117. const char* const no_txt =
  118. ").no.example.com. 3600 IN AAAA 2001:db8::53\n";
  119. // NSEC records.
  120. const char* const nsec_apex_txt =
  121. "example.com. 3600 IN NSEC cname.example.com. NS SOA NSEC RRSIG\n";
  122. const char* const nsec_mx_txt =
  123. "mx.example.com. 3600 IN NSEC ).no.example.com. MX NSEC RRSIG\n";
  124. const char* const nsec_no_txt =
  125. ").no.example.com. 3600 IN NSEC nz.no.example.com. AAAA NSEC RRSIG\n";
  126. // We'll also test the case where a single NSEC proves both NXDOMAIN and the
  127. // non existence of wildcard. The following records will be used for that
  128. // test.
  129. // ).no.example.com. (exist, whose NSEC proves everything)
  130. // *.no.example.com. (best possible wildcard, not exist)
  131. // nx.no.example.com. (NXDOMAIN)
  132. // nz.no.example.com. (exist)
  133. const char* const nz_txt =
  134. "nz.no.example.com. 3600 IN AAAA 2001:db8::5300\n";
  135. const char* const nsec_nz_txt =
  136. "nz.no.example.com. 3600 IN NSEC noglue.example.com. AAAA NSEC RRSIG\n";
  137. const char* const nsec_nxdomain_txt =
  138. "noglue.example.com. 3600 IN NSEC nonsec.example.com. A\n";
  139. // NSEC for the normal NXRRSET case
  140. const char* const nsec_www_txt =
  141. "www.example.com. 3600 IN NSEC example.com. A NSEC RRSIG\n";
  142. // Authoritative data without NSEC
  143. const char* const nonsec_a_txt = "nonsec.example.com. 3600 IN A 192.0.2.0\n";
  144. // NSEC3 RRs. You may also need to add mapping to MockZoneFinder::hash_map_.
  145. const char* const nsec3_apex_txt =
  146. "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example.com. 3600 IN NSEC3 1 1 12 "
  147. "aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA NSEC3PARAM RRSIG\n";
  148. const char* const nsec3_www_txt =
  149. "q04jkcevqvmu85r014c7dkba38o0ji5r.example.com. 3600 IN NSEC3 1 1 12 "
  150. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG\n";
  151. // (Secure) delegation data; Delegation with DS record
  152. const char* const signed_delegation_txt =
  153. "signed-delegation.example.com. 3600 IN NS ns.example.net.\n";
  154. const char* const signed_delegation_ds_txt =
  155. "signed-delegation.example.com. 3600 IN DS 12345 8 2 "
  156. "764501411DE58E8618945054A3F620B36202E115D015A7773F4B78E0F952CECA\n";
  157. // (Secure) delegation data; Delegation without DS record (and NSEC denying
  158. // its existence.
  159. const char* const unsigned_delegation_txt =
  160. "unsigned-delegation.example.com. 3600 IN NS ns.example.net.\n";
  161. const char* const unsigned_delegation_nsec_txt =
  162. "unsigned-delegation.example.com. 3600 IN NSEC "
  163. "*.uwild.example.com. NS RRSIG NSEC\n";
  164. // (Secure) delegation data; Delegation where the DS lookup will raise an
  165. // exception.
  166. const char* const bad_delegation_txt =
  167. "bad-delegation.example.com. 3600 IN NS ns.example.net.\n";
  168. // A helper function that generates a textual representation of RRSIG RDATA
  169. // for the given covered type. The resulting RRSIG may not necessarily make
  170. // sense in terms of the DNSSEC protocol, but for our testing purposes it's
  171. // okay.
  172. string
  173. getCommonRRSIGText(const string& type) {
  174. return (type +
  175. string(" 5 3 3600 20000101000000 20000201000000 12345 "
  176. "example.com. FAKEFAKEFAKE"));
  177. }
  178. // A helper callback of masterLoad() used in InMemoryZoneFinderTest.
  179. void
  180. setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
  181. *(*it) = rrset;
  182. ++it;
  183. }
  184. // A helper function that converts a textual form of a single RR into a
  185. // RRsetPtr object. If it's SOA, origin must be set to its owner name;
  186. // otherwise masterLoad() will reject it.
  187. RRsetPtr
  188. textToRRset(const string& text_rrset, const Name& origin = Name::ROOT_NAME()) {
  189. stringstream ss(text_rrset);
  190. RRsetPtr rrset;
  191. vector<RRsetPtr*> rrsets;
  192. rrsets.push_back(&rrset);
  193. masterLoad(ss, origin, RRClass::IN(),
  194. boost::bind(setRRset, _1, rrsets.begin()));
  195. return (rrset);
  196. }
  197. // This is a mock Zone Finder class for testing.
  198. // It is a derived class of ZoneFinder for the convenient of tests.
  199. // Its find() method emulates the common behavior of protocol compliant
  200. // ZoneFinder classes, but simplifies some minor cases and also supports broken
  201. // behavior.
  202. // For simplicity, most names are assumed to be "in zone"; there's only
  203. // one zone cut at the point of name "delegation.example.com".
  204. // Another special name is "dname.example.com". Query names under this name
  205. // will result in DNAME.
  206. // This mock zone doesn't handle empty non terminal nodes (if we need to test
  207. // such cases find() should have specialized code for it).
  208. class MockZoneFinder : public ZoneFinder {
  209. public:
  210. MockZoneFinder() :
  211. origin_(Name("example.com")),
  212. delegation_name_("delegation.example.com"),
  213. signed_delegation_name_("signed-delegation.example.com"),
  214. bad_signed_delegation_name_("bad-delegation.example.com"),
  215. unsigned_delegation_name_("unsigned-delegation.example.com"),
  216. dname_name_("dname.example.com"),
  217. has_SOA_(true),
  218. has_apex_NS_(true),
  219. rrclass_(RRClass::IN()),
  220. include_rrsig_anyway_(false),
  221. use_nsec3_(false),
  222. nsec_name_(origin_),
  223. nsec3_fake_(NULL)
  224. {
  225. stringstream zone_stream;
  226. zone_stream << soa_txt << zone_ns_txt << ns_addrs_txt <<
  227. delegation_txt << mx_txt << www_a_txt << cname_txt <<
  228. cname_nxdom_txt << cname_out_txt << dname_txt <<
  229. dname_a_txt << other_zone_rrs << no_txt << nz_txt <<
  230. nsec_apex_txt << nsec_mx_txt << nsec_no_txt << nsec_nz_txt <<
  231. nsec_nxdomain_txt << nsec_www_txt << nonsec_a_txt <<
  232. wild_txt << nsec_wild_txt << cnamewild_txt << nsec_cnamewild_txt <<
  233. wild_txt_nxrrset << nsec_wild_txt_nxrrset << wild_txt_next <<
  234. nsec_wild_txt_next << empty_txt << nsec_empty_txt <<
  235. empty_prev_txt << nsec_empty_prev_txt <<
  236. nsec3_apex_txt << nsec3_www_txt <<
  237. signed_delegation_txt << signed_delegation_ds_txt <<
  238. unsigned_delegation_txt << unsigned_delegation_nsec_txt <<
  239. bad_delegation_txt;
  240. masterLoad(zone_stream, origin_, rrclass_,
  241. boost::bind(&MockZoneFinder::loadRRset, this, _1));
  242. empty_nsec_rrset_ = ConstRRsetPtr(new RRset(Name::ROOT_NAME(),
  243. RRClass::IN(),
  244. RRType::NSEC(),
  245. RRTTL(3600)));
  246. // (Faked) NSEC3 hash map. For convenience we use hardcoded built-in
  247. // map instead of calculating and using actual hash.
  248. // The used hash values are borrowed from RFC5155 examples.
  249. hash_map_[Name("example.com")] = "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom";
  250. hash_map_[Name("nxdomain.example.com")] =
  251. "v644ebqk9bibcna874givr6joj62mlhv";
  252. hash_map_[Name("nx.domain.example.com")] =
  253. "v644ebqk9bibcna874givr6joj62mlhv";
  254. hash_map_[Name("domain.example.com")] =
  255. "v644ebqk9bibcna874givr6joj62mlhv";
  256. hash_map_[Name("nxdomain2.example.com")] =
  257. "q00jkcevqvmu85r014c7dkba38o0ji5r";
  258. hash_map_[Name("nxdomain3.example.com")] =
  259. "009mhaveqvm6t7vbl5lop2u3t2rp3tom";
  260. hash_map_[Name("*.example.com")] =
  261. "r53bq7cc2uvmubfu5ocmm6pers9tk9en";
  262. }
  263. virtual isc::dns::Name getOrigin() const { return (origin_); }
  264. virtual isc::dns::RRClass getClass() const { return (rrclass_); }
  265. virtual FindResult find(const isc::dns::Name& name,
  266. const isc::dns::RRType& type,
  267. const FindOptions options = FIND_DEFAULT);
  268. virtual FindResult findAll(const isc::dns::Name& name,
  269. std::vector<ConstRRsetPtr>& target,
  270. const FindOptions options = FIND_DEFAULT);
  271. virtual ZoneFinder::FindNSEC3Result
  272. findNSEC3(const Name& name, bool recursive);
  273. // If false is passed, it makes the zone broken as if it didn't have the
  274. // SOA.
  275. void setSOAFlag(bool on) { has_SOA_ = on; }
  276. // If false is passed, it makes the zone broken as if it didn't have
  277. // the apex NS.
  278. void setApexNSFlag(bool on) { has_apex_NS_ = on; }
  279. // Turn this on if you want it to return RRSIGs regardless of FIND_GLUE_OK
  280. void setIncludeRRSIGAnyway(bool on) { include_rrsig_anyway_ = on; }
  281. // Once called, this "faked" result will be returned when NSEC is expected
  282. // for the specified query name.
  283. void setNSECResult(const Name& nsec_name, Result code,
  284. ConstRRsetPtr rrset)
  285. {
  286. nsec_name_ = nsec_name;
  287. nsec_result_.reset(new ZoneFinder::FindResult(code, rrset));
  288. }
  289. // Once called, the findNSEC3 will return the provided result for the next
  290. // query. After that, it'll return to operate normally.
  291. // NULL disables. Does not take ownership of the pointer (it is generally
  292. // expected to be a local variable in the test function).
  293. void setNSEC3Result(const FindNSEC3Result* result) {
  294. nsec3_fake_ = result;
  295. }
  296. // If true is passed return an empty NSEC3 RRset for some negative
  297. // answers when DNSSEC is required.
  298. void setNSEC3Flag(bool on) { use_nsec3_ = on; }
  299. Name findPreviousName(const Name&) const {
  300. isc_throw(isc::NotImplemented, "Mock doesn't support previous name");
  301. }
  302. public:
  303. // We allow the tests to use these for convenience
  304. ConstRRsetPtr delegation_rrset_;
  305. ConstRRsetPtr signed_delegation_rrset_;
  306. ConstRRsetPtr signed_delegation_ds_rrset_;
  307. ConstRRsetPtr bad_signed_delegation_rrset_;
  308. ConstRRsetPtr unsigned_delegation_rrset_;
  309. ConstRRsetPtr empty_nsec_rrset_;
  310. private:
  311. typedef map<RRType, ConstRRsetPtr> RRsetStore;
  312. typedef map<Name, RRsetStore> Domains;
  313. Domains domains_;
  314. Domains nsec3_domains_;
  315. void loadRRset(RRsetPtr rrset) {
  316. if (rrset->getType() == RRType::NSEC3()) {
  317. // NSEC3 should go to the dedicated table
  318. nsec3_domains_[rrset->getName()][rrset->getType()] = rrset;
  319. // By nature it should have RRSIG. (We may want to selectively
  320. // omit this to test pathological cases).
  321. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  322. getCommonRRSIGText(rrset->getType().
  323. toText()))));
  324. return;
  325. }
  326. domains_[rrset->getName()][rrset->getType()] = rrset;
  327. if (rrset->getName() == delegation_name_ &&
  328. rrset->getType() == RRType::NS()) {
  329. delegation_rrset_ = rrset;
  330. } else if (rrset->getName() == signed_delegation_name_ &&
  331. rrset->getType() == RRType::NS()) {
  332. signed_delegation_rrset_ = rrset;
  333. } else if (rrset->getName() == bad_signed_delegation_name_ &&
  334. rrset->getType() == RRType::NS()) {
  335. bad_signed_delegation_rrset_ = rrset;
  336. } else if (rrset->getName() == unsigned_delegation_name_ &&
  337. rrset->getType() == RRType::NS()) {
  338. unsigned_delegation_rrset_ = rrset;
  339. } else if (rrset->getName() == signed_delegation_name_ &&
  340. rrset->getType() == RRType::DS()) {
  341. signed_delegation_ds_rrset_ = rrset;
  342. // Like NSEC(3), by nature it should have an RRSIG.
  343. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  344. getCommonRRSIGText(rrset->getType().
  345. toText()))));
  346. } else if (rrset->getName() == dname_name_ &&
  347. rrset->getType() == RRType::DNAME()) {
  348. dname_rrset_ = rrset;
  349. // Add some signatures
  350. } else if (rrset->getName() == Name("example.com.") &&
  351. rrset->getType() == RRType::NS()) {
  352. // For NS, we only have RRSIG for the origin name.
  353. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  354. getCommonRRSIGText("NS"))));
  355. } else {
  356. // For others generate RRSIG unconditionally. Technically this
  357. // is wrong because we shouldn't have it for names under a zone
  358. // cut. But in our tests that doesn't matter, so we add them
  359. // just for simplicity.
  360. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  361. getCommonRRSIGText(rrset->getType().
  362. toText()))));
  363. }
  364. }
  365. const Name origin_;
  366. // Names where we delegate somewhere else
  367. const Name delegation_name_;
  368. const Name signed_delegation_name_;
  369. const Name bad_signed_delegation_name_;
  370. const Name unsigned_delegation_name_;
  371. const Name dname_name_;
  372. bool has_SOA_;
  373. bool has_apex_NS_;
  374. ConstRRsetPtr dname_rrset_;
  375. const RRClass rrclass_;
  376. bool include_rrsig_anyway_;
  377. bool use_nsec3_;
  378. // The following two will be used for faked NSEC cases
  379. Name nsec_name_;
  380. boost::scoped_ptr<ZoneFinder::FindResult> nsec_result_;
  381. map<Name, string> hash_map_;
  382. // The following two are for faking bad NSEC3 responses
  383. // Enabled when not NULL
  384. const FindNSEC3Result* nsec3_fake_;
  385. };
  386. // A helper function that generates a new RRset based on "wild_rrset",
  387. // replacing its owner name with 'real_name'.
  388. ConstRRsetPtr
  389. substituteWild(const AbstractRRset& wild_rrset, const Name& real_name) {
  390. RRsetPtr rrset(new RRset(real_name, wild_rrset.getClass(),
  391. wild_rrset.getType(), wild_rrset.getTTL()));
  392. // For simplicity we only consider the case with one RDATA (for now)
  393. rrset->addRdata(wild_rrset.getRdataIterator()->getCurrent());
  394. ConstRRsetPtr wild_sig = wild_rrset.getRRsig();
  395. if (wild_sig) {
  396. RRsetPtr sig(new RRset(real_name, wild_sig->getClass(),
  397. wild_sig->getType(), wild_sig->getTTL()));
  398. sig->addRdata(wild_sig->getRdataIterator()->getCurrent());
  399. rrset->addRRsig(sig);
  400. }
  401. return (rrset);
  402. }
  403. ZoneFinder::FindResult
  404. MockZoneFinder::findAll(const Name& name, std::vector<ConstRRsetPtr>& target,
  405. const FindOptions options)
  406. {
  407. ZoneFinder::FindResult result(find(name, RRType::ANY(), options));
  408. if (result.code == NXRRSET) {
  409. const Domains::const_iterator found_domain = domains_.find(name);
  410. if (!found_domain->second.empty()) {
  411. for (RRsetStore::const_iterator found_rrset =
  412. found_domain->second.begin();
  413. found_rrset != found_domain->second.end(); ++found_rrset) {
  414. // Insert RRs under the domain name into target
  415. target.push_back(found_rrset->second);
  416. }
  417. return (FindResult(SUCCESS, RRsetPtr()));
  418. }
  419. }
  420. return (result);
  421. }
  422. ZoneFinder::FindNSEC3Result
  423. MockZoneFinder::findNSEC3(const Name& name, bool recursive) {
  424. // Do we have a fake result set? If so, use it.
  425. if (nsec3_fake_ != NULL) {
  426. const FindNSEC3Result* result(nsec3_fake_);
  427. return (*result);
  428. }
  429. ConstRRsetPtr covering_proof;
  430. const int labels = name.getLabelCount();
  431. // For brevity, we assume several things below: maps should have an
  432. // expected entry when operator[] is used; maps are not empty.
  433. for (int i = 0; i < labels; ++i) {
  434. const string hlabel = hash_map_[name.split(i, labels - i)];
  435. const Name hname = Name(hlabel + ".example.com");
  436. // We don't use const_iterator so that we can use operator[] below
  437. Domains::iterator found_domain = nsec3_domains_.lower_bound(hname);
  438. // If the given hash is larger than the largest stored hash or
  439. // the first label doesn't match the target, identify the "previous"
  440. // hash value and remember it as the candidate next closer proof.
  441. if (found_domain == nsec3_domains_.end() ||
  442. found_domain->first.split(0, 1).toText(true) != hlabel) {
  443. // If the given hash is larger or smaller than everything,
  444. // the covering proof is the NSEC3 that has the largest hash.
  445. if (found_domain == nsec3_domains_.end() ||
  446. found_domain == nsec3_domains_.begin()) {
  447. covering_proof =
  448. nsec3_domains_.rbegin()->second[RRType::NSEC3()];
  449. } else {
  450. // Otherwise, H(found_domain-1) < given_hash < H(found_domain)
  451. // The covering proof is the first one.
  452. covering_proof = (--found_domain)->second[RRType::NSEC3()];
  453. }
  454. if (!recursive) { // in non recursive mode, we are done.
  455. return (ZoneFinder::FindNSEC3Result(false,
  456. name.getLabelCount(),
  457. covering_proof,
  458. ConstRRsetPtr()));
  459. }
  460. } else { // exact match
  461. return (ZoneFinder::FindNSEC3Result(
  462. true, name.getLabelCount() - i,
  463. found_domain->second[RRType::NSEC3()],
  464. covering_proof));
  465. }
  466. }
  467. isc_throw(isc::Unexpected, "findNSEC3() isn't expected to fail");
  468. }
  469. ZoneFinder::FindResult
  470. MockZoneFinder::find(const Name& name, const RRType& type,
  471. const FindOptions options)
  472. {
  473. // Emulating a broken zone: mandatory apex RRs are missing if specifically
  474. // configured so (which are rare cases).
  475. if (name == origin_ && type == RRType::SOA() && !has_SOA_) {
  476. return (FindResult(NXDOMAIN, RRsetPtr()));
  477. } else if (name == origin_ && type == RRType::NS() && !has_apex_NS_) {
  478. return (FindResult(NXDOMAIN, RRsetPtr()));
  479. }
  480. // Special case for names on or under a zone cut
  481. if ((options & FIND_GLUE_OK) == 0 &&
  482. (name == delegation_name_ ||
  483. name.compare(delegation_name_).getRelation() ==
  484. NameComparisonResult::SUBDOMAIN)) {
  485. return (FindResult(DELEGATION, delegation_rrset_));
  486. // And under DNAME
  487. } else if (name.compare(dname_name_).getRelation() ==
  488. NameComparisonResult::SUBDOMAIN) {
  489. if (type != RRType::DS()) {
  490. return (FindResult(DNAME, dname_rrset_));
  491. }
  492. } else if (name == signed_delegation_name_ ||
  493. name.compare(signed_delegation_name_).getRelation() ==
  494. NameComparisonResult::SUBDOMAIN) {
  495. if (type != RRType::DS()) {
  496. return (FindResult(DELEGATION, signed_delegation_rrset_));
  497. } else {
  498. return (FindResult(SUCCESS, signed_delegation_ds_rrset_));
  499. }
  500. } else if (name == unsigned_delegation_name_ ||
  501. name.compare(unsigned_delegation_name_).getRelation() ==
  502. NameComparisonResult::SUBDOMAIN) {
  503. if (type != RRType::DS()) {
  504. return (FindResult(DELEGATION, unsigned_delegation_rrset_));
  505. }
  506. } else if (name == bad_signed_delegation_name_ ||
  507. name.compare(bad_signed_delegation_name_).getRelation() ==
  508. NameComparisonResult::SUBDOMAIN) {
  509. if (type != RRType::DS()) {
  510. return (FindResult(DELEGATION, bad_signed_delegation_rrset_));
  511. } else {
  512. return (FindResult(NXDOMAIN, RRsetPtr()));
  513. }
  514. }
  515. // normal cases. names are searched for only per exact-match basis
  516. // for simplicity.
  517. const Domains::const_iterator found_domain = domains_.find(name);
  518. if (found_domain != domains_.end()) {
  519. // First, try exact match.
  520. RRsetStore::const_iterator found_rrset =
  521. found_domain->second.find(type);
  522. if (found_rrset != found_domain->second.end()) {
  523. ConstRRsetPtr rrset;
  524. // Strip whatever signature there is in case DNSSEC is not required
  525. // Just to make sure the Query asks for it when it is needed
  526. if ((options & ZoneFinder::FIND_DNSSEC) != 0 ||
  527. include_rrsig_anyway_ ||
  528. !found_rrset->second->getRRsig()) {
  529. rrset = found_rrset->second;
  530. } else {
  531. RRsetPtr noconst(new RRset(found_rrset->second->getName(),
  532. found_rrset->second->getClass(),
  533. found_rrset->second->getType(),
  534. found_rrset->second->getTTL()));
  535. for (RdataIteratorPtr
  536. i(found_rrset->second->getRdataIterator());
  537. !i->isLast(); i->next()) {
  538. noconst->addRdata(i->getCurrent());
  539. }
  540. rrset = noconst;
  541. }
  542. return (FindResult(SUCCESS, rrset));
  543. }
  544. // Otherwise, if this domain name has CNAME, return it.
  545. found_rrset = found_domain->second.find(RRType::CNAME());
  546. if (found_rrset != found_domain->second.end()) {
  547. return (FindResult(CNAME, found_rrset->second));
  548. }
  549. // Otherwise it's NXRRSET case.
  550. if ((options & FIND_DNSSEC) != 0) {
  551. if (use_nsec3_) {
  552. return (FindResult(NXRRSET, RRsetPtr(), RESULT_NSEC3_SIGNED));
  553. }
  554. found_rrset = found_domain->second.find(RRType::NSEC());
  555. if (found_rrset != found_domain->second.end()) {
  556. return (FindResult(NXRRSET, found_rrset->second,
  557. RESULT_NSEC_SIGNED));
  558. }
  559. }
  560. return (FindResult(NXRRSET, RRsetPtr(), RESULT_NSEC_SIGNED));
  561. }
  562. // query name isn't found in our domains.
  563. // We first check if the query name is an empty non terminal name
  564. // of the zone by naive linear search.
  565. Domains::const_iterator domain;
  566. for (domain = domains_.begin(); domain != domains_.end(); ++domain) {
  567. if (name.compare((*domain).first).getRelation() ==
  568. NameComparisonResult::SUPERDOMAIN) {
  569. break;
  570. }
  571. }
  572. if (domain != domains_.end()) {
  573. // The query name is in an empty non terminal node followed by 'domain'
  574. // (for simplicity we ignore the pathological case of 'domain' is
  575. // the origin of the zone)
  576. --domain; // reset domain to the "previous name"
  577. if ((options & FIND_DNSSEC) != 0) {
  578. if (use_nsec3_) {
  579. return (FindResult(NXRRSET, RRsetPtr(), RESULT_NSEC3_SIGNED));
  580. }
  581. RRsetStore::const_iterator found_rrset =
  582. (*domain).second.find(RRType::NSEC());
  583. if (found_rrset != (*domain).second.end()) {
  584. return (FindResult(NXRRSET, found_rrset->second,
  585. RESULT_NSEC_SIGNED));
  586. }
  587. }
  588. return (FindResult(NXRRSET, RRsetPtr()));
  589. }
  590. // Another possibility is wildcard. For simplicity we only check
  591. // hardcoded specific cases, ignoring other details such as canceling
  592. // due to the existence of closer name.
  593. if ((options & NO_WILDCARD) == 0) {
  594. const Name wild_suffix(name.split(1));
  595. // Unit Tests use those domains for Wildcard test.
  596. if (name.equals(Name("www.wild.example.com"))||
  597. name.equals(Name("www1.uwild.example.com"))||
  598. name.equals(Name("a.t.example.com"))) {
  599. if (name.compare(wild_suffix).getRelation() ==
  600. NameComparisonResult::SUBDOMAIN) {
  601. domain = domains_.find(Name("*").concatenate(wild_suffix));
  602. // Matched the QNAME
  603. if (domain != domains_.end()) {
  604. RRsetStore::const_iterator found_rrset =
  605. domain->second.find(type);
  606. // Matched the QTYPE
  607. if(found_rrset != domain->second.end()) {
  608. return (FindResult(SUCCESS,
  609. substituteWild(
  610. *found_rrset->second, name),
  611. RESULT_WILDCARD |
  612. (use_nsec3_ ?
  613. RESULT_NSEC3_SIGNED :
  614. RESULT_NSEC_SIGNED)));
  615. } else {
  616. // No matched QTYPE, this case is for WILDCARD_NXRRSET
  617. if (use_nsec3_) {
  618. return (FindResult(NXRRSET, RRsetPtr(),
  619. RESULT_WILDCARD |
  620. RESULT_NSEC3_SIGNED));
  621. }
  622. const Name new_name =
  623. Name("*").concatenate(wild_suffix);
  624. found_rrset = domain->second.find(RRType::NSEC());
  625. assert(found_rrset != domain->second.end());
  626. return (FindResult(NXRRSET,
  627. substituteWild(
  628. *found_rrset->second,
  629. new_name),
  630. RESULT_WILDCARD |
  631. RESULT_NSEC_SIGNED));
  632. }
  633. } else {
  634. // This is empty non terminal name case on wildcard.
  635. const Name empty_name = Name("*").concatenate(wild_suffix);
  636. if (use_nsec3_) {
  637. return (FindResult(NXRRSET, RRsetPtr(),
  638. RESULT_WILDCARD |
  639. RESULT_NSEC3_SIGNED));
  640. }
  641. for (Domains::reverse_iterator it = domains_.rbegin();
  642. it != domains_.rend();
  643. ++it) {
  644. RRsetStore::const_iterator nsec_it;
  645. if ((*it).first < empty_name &&
  646. (nsec_it = (*it).second.find(RRType::NSEC()))
  647. != (*it).second.end()) {
  648. return (FindResult(NXRRSET, (*nsec_it).second,
  649. RESULT_WILDCARD |
  650. RESULT_NSEC_SIGNED));
  651. }
  652. }
  653. }
  654. return (FindResult(NXRRSET, RRsetPtr(), RESULT_WILDCARD));
  655. }
  656. }
  657. const Name cnamewild_suffix("cnamewild.example.com");
  658. if (name.compare(cnamewild_suffix).getRelation() ==
  659. NameComparisonResult::SUBDOMAIN) {
  660. domain = domains_.find(Name("*").concatenate(cnamewild_suffix));
  661. assert(domain != domains_.end());
  662. RRsetStore::const_iterator found_rrset =
  663. domain->second.find(RRType::CNAME());
  664. assert(found_rrset != domain->second.end());
  665. return (FindResult(CNAME,
  666. substituteWild(*found_rrset->second, name),
  667. RESULT_WILDCARD |
  668. (use_nsec3_ ? RESULT_NSEC3_SIGNED :
  669. RESULT_NSEC_SIGNED)));
  670. }
  671. }
  672. // This is an NXDOMAIN case.
  673. // If we need DNSSEC proof, find the "previous name" that has an NSEC RR
  674. // and return NXDOMAIN with the found NSEC. Otherwise, just return the
  675. // NXDOMAIN code and NULL. If DNSSEC proof is requested but no NSEC is
  676. // found, we return NULL, too. (For simplicity under the test conditions
  677. // we don't care about pathological cases such as the name is "smaller"
  678. // than the origin)
  679. if ((options & FIND_DNSSEC) != 0) {
  680. if (use_nsec3_) {
  681. return (FindResult(NXDOMAIN, RRsetPtr(), RESULT_NSEC3_SIGNED));
  682. }
  683. // Emulate a broken DataSourceClient for some special names.
  684. if (nsec_result_ && nsec_name_ == name) {
  685. return (*nsec_result_);
  686. }
  687. // Normal case
  688. // XXX: some older g++ complains about operator!= if we use
  689. // const_reverse_iterator
  690. for (Domains::reverse_iterator it = domains_.rbegin();
  691. it != domains_.rend();
  692. ++it) {
  693. RRsetStore::const_iterator nsec_it;
  694. if ((*it).first < name &&
  695. (nsec_it = (*it).second.find(RRType::NSEC()))
  696. != (*it).second.end()) {
  697. return (FindResult(NXDOMAIN, (*nsec_it).second,
  698. RESULT_NSEC_SIGNED));
  699. }
  700. }
  701. }
  702. return (FindResult(NXDOMAIN, RRsetPtr()));
  703. }
  704. class QueryTest : public ::testing::Test {
  705. protected:
  706. QueryTest() :
  707. qname(Name("www.example.com")), qclass(RRClass::IN()),
  708. qtype(RRType::A()), response(Message::RENDER),
  709. qid(response.getQid()), query_code(Opcode::QUERY().getCode())
  710. {
  711. response.setRcode(Rcode::NOERROR());
  712. response.setOpcode(Opcode::QUERY());
  713. // create and add a matching zone.
  714. mock_finder = new MockZoneFinder();
  715. memory_client.addZone(ZoneFinderPtr(mock_finder));
  716. }
  717. MockZoneFinder* mock_finder;
  718. // We use InMemoryClient here. We could have some kind of mock client
  719. // here, but historically, the Query supported only InMemoryClient
  720. // (originally named MemoryDataSrc) and was tested with it, so we keep
  721. // it like this for now.
  722. InMemoryClient memory_client;
  723. const Name qname;
  724. const RRClass qclass;
  725. const RRType qtype;
  726. Message response;
  727. const qid_t qid;
  728. const uint16_t query_code;
  729. };
  730. // A wrapper to check resulting response message commonly used in
  731. // tests below.
  732. // check_origin needs to be specified only when the authority section has
  733. // an SOA RR. The interface is not generic enough but should be okay
  734. // for our test cases in practice.
  735. void
  736. responseCheck(Message& response, const isc::dns::Rcode& rcode,
  737. unsigned int flags, const unsigned int ancount,
  738. const unsigned int nscount, const unsigned int arcount,
  739. const char* const expected_answer,
  740. const char* const expected_authority,
  741. const char* const expected_additional,
  742. const Name& check_origin = Name::ROOT_NAME())
  743. {
  744. // In our test cases QID, Opcode, and QDCOUNT should be constant, so
  745. // we don't bother the test cases specifying these values.
  746. headerCheck(response, response.getQid(), rcode, Opcode::QUERY().getCode(),
  747. flags, 0, ancount, nscount, arcount);
  748. if (expected_answer != NULL) {
  749. rrsetsCheck(expected_answer,
  750. response.beginSection(Message::SECTION_ANSWER),
  751. response.endSection(Message::SECTION_ANSWER),
  752. check_origin);
  753. }
  754. if (expected_authority != NULL) {
  755. rrsetsCheck(expected_authority,
  756. response.beginSection(Message::SECTION_AUTHORITY),
  757. response.endSection(Message::SECTION_AUTHORITY),
  758. check_origin);
  759. }
  760. if (expected_additional != NULL) {
  761. rrsetsCheck(expected_additional,
  762. response.beginSection(Message::SECTION_ADDITIONAL),
  763. response.endSection(Message::SECTION_ADDITIONAL));
  764. }
  765. }
  766. TEST_F(QueryTest, noZone) {
  767. // There's no zone in the memory datasource. So the response should have
  768. // REFUSED.
  769. InMemoryClient empty_memory_client;
  770. Query nozone_query(empty_memory_client, qname, qtype, response);
  771. EXPECT_NO_THROW(nozone_query.process());
  772. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  773. }
  774. TEST_F(QueryTest, exactMatch) {
  775. Query query(memory_client, qname, qtype, response);
  776. EXPECT_NO_THROW(query.process());
  777. // find match rrset
  778. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  779. www_a_txt, zone_ns_txt, ns_addrs_txt);
  780. }
  781. TEST_F(QueryTest, exactMatchIgnoreSIG) {
  782. // Check that we do not include the RRSIG when not requested even when
  783. // we receive it from the data source.
  784. mock_finder->setIncludeRRSIGAnyway(true);
  785. Query query(memory_client, qname, qtype, response);
  786. EXPECT_NO_THROW(query.process());
  787. // find match rrset
  788. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  789. www_a_txt, zone_ns_txt, ns_addrs_txt);
  790. }
  791. TEST_F(QueryTest, dnssecPositive) {
  792. // Just like exactMatch, but the signatures should be included as well
  793. Query query(memory_client, qname, qtype, response, true);
  794. EXPECT_NO_THROW(query.process());
  795. // find match rrset
  796. // We can't let responseCheck to check the additional section as well,
  797. // it gets confused by the two RRs for glue.delegation.../RRSIG due
  798. // to it's design and fixing it would be hard. Therefore we simply
  799. // check manually this one time.
  800. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 4, 6,
  801. (www_a_txt + std::string("www.example.com. 3600 IN RRSIG "
  802. "A 5 3 3600 20000101000000 "
  803. "20000201000000 12345 example.com. "
  804. "FAKEFAKEFAKE\n")).c_str(),
  805. (zone_ns_txt + std::string("example.com. 3600 IN RRSIG NS 5 "
  806. "3 3600 20000101000000 "
  807. "20000201000000 12345 "
  808. "example.com. FAKEFAKEFAKE\n")).
  809. c_str(), NULL);
  810. RRsetIterator iterator(response.beginSection(Message::SECTION_ADDITIONAL));
  811. const char* additional[] = {
  812. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n",
  813. "glue.delegation.example.com. 3600 IN RRSIG A 5 3 3600 20000101000000 "
  814. "20000201000000 12345 example.com. FAKEFAKEFAKE\n",
  815. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n",
  816. "glue.delegation.example.com. 3600 IN RRSIG AAAA 5 3 3600 "
  817. "20000101000000 20000201000000 12345 example.com. FAKEFAKEFAKE\n",
  818. "noglue.example.com. 3600 IN A 192.0.2.53\n",
  819. "noglue.example.com. 3600 IN RRSIG A 5 3 3600 20000101000000 "
  820. "20000201000000 12345 example.com. FAKEFAKEFAKE\n",
  821. NULL
  822. };
  823. for (const char** rr(additional); *rr != NULL; ++ rr) {
  824. ASSERT_FALSE(iterator ==
  825. response.endSection(Message::SECTION_ADDITIONAL));
  826. EXPECT_EQ(*rr, (*iterator)->toText());
  827. iterator ++;
  828. }
  829. EXPECT_TRUE(iterator == response.endSection(Message::SECTION_ADDITIONAL));
  830. }
  831. TEST_F(QueryTest, exactAddrMatch) {
  832. // find match rrset, omit additional data which has already been provided
  833. // in the answer section from the additional.
  834. EXPECT_NO_THROW(Query(memory_client, Name("noglue.example.com"), qtype,
  835. response).process());
  836. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 2,
  837. "noglue.example.com. 3600 IN A 192.0.2.53\n", zone_ns_txt,
  838. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  839. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
  840. }
  841. TEST_F(QueryTest, apexNSMatch) {
  842. // find match rrset, omit authority data which has already been provided
  843. // in the answer section from the authority section.
  844. EXPECT_NO_THROW(Query(memory_client, Name("example.com"), RRType::NS(),
  845. response).process());
  846. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 3, 0, 3,
  847. zone_ns_txt, NULL, ns_addrs_txt);
  848. }
  849. // test type any query logic
  850. TEST_F(QueryTest, exactAnyMatch) {
  851. // find match rrset, omit additional data which has already been provided
  852. // in the answer section from the additional.
  853. EXPECT_NO_THROW(Query(memory_client, Name("noglue.example.com"),
  854. RRType::ANY(), response).process());
  855. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 3, 2,
  856. (string("noglue.example.com. 3600 IN A 192.0.2.53\n") +
  857. string(nsec_nxdomain_txt)).c_str(),
  858. zone_ns_txt,
  859. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  860. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
  861. }
  862. TEST_F(QueryTest, apexAnyMatch) {
  863. // find match rrset, omit additional data which has already been provided
  864. // in the answer section from the additional.
  865. EXPECT_NO_THROW(Query(memory_client, Name("example.com"),
  866. RRType::ANY(), response).process());
  867. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 5, 0, 3,
  868. (string(soa_txt) + string(zone_ns_txt) +
  869. string(nsec_apex_txt)).c_str(),
  870. NULL, ns_addrs_txt, mock_finder->getOrigin());
  871. }
  872. TEST_F(QueryTest, mxANYMatch) {
  873. EXPECT_NO_THROW(Query(memory_client, Name("mx.example.com"),
  874. RRType::ANY(), response).process());
  875. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 4, 3, 4,
  876. (string(mx_txt) + string(nsec_mx_txt)).c_str(), zone_ns_txt,
  877. (string(ns_addrs_txt) + string(www_a_txt)).c_str());
  878. }
  879. TEST_F(QueryTest, glueANYMatch) {
  880. EXPECT_NO_THROW(Query(memory_client, Name("delegation.example.com"),
  881. RRType::ANY(), response).process());
  882. responseCheck(response, Rcode::NOERROR(), 0, 0, 4, 3,
  883. NULL, delegation_txt, ns_addrs_txt);
  884. }
  885. TEST_F(QueryTest, nodomainANY) {
  886. EXPECT_NO_THROW(Query(memory_client, Name("nxdomain.example.com"),
  887. RRType::ANY(), response).process());
  888. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 1, 0,
  889. NULL, soa_txt, NULL, mock_finder->getOrigin());
  890. }
  891. // This tests that when we need to look up Zone's apex NS records for
  892. // authoritative answer, and there is no apex NS records. It should
  893. // throw in that case.
  894. TEST_F(QueryTest, noApexNS) {
  895. // Disable apex NS record
  896. mock_finder->setApexNSFlag(false);
  897. EXPECT_THROW(Query(memory_client, Name("noglue.example.com"), qtype,
  898. response).process(), Query::NoApexNS);
  899. // We don't look into the response, as it threw
  900. }
  901. TEST_F(QueryTest, delegation) {
  902. EXPECT_NO_THROW(Query(memory_client, Name("delegation.example.com"),
  903. qtype, response).process());
  904. responseCheck(response, Rcode::NOERROR(), 0, 0, 4, 3,
  905. NULL, delegation_txt, ns_addrs_txt);
  906. }
  907. TEST_F(QueryTest, secureDelegation) {
  908. EXPECT_NO_THROW(Query(memory_client,
  909. Name("foo.signed-delegation.example.com"),
  910. qtype, response, true).process());
  911. // Should now contain RRSIG and DS record as well.
  912. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  913. NULL,
  914. (string(signed_delegation_txt) +
  915. string(signed_delegation_ds_txt) +
  916. string("signed-delegation.example.com. 3600 IN RRSIG ") +
  917. getCommonRRSIGText("DS")).c_str(),
  918. NULL);
  919. }
  920. TEST_F(QueryTest, secureUnsignedDelegation) {
  921. EXPECT_NO_THROW(Query(memory_client,
  922. Name("foo.unsigned-delegation.example.com"),
  923. qtype, response, true).process());
  924. // Should now contain RRSIG and NSEC record as well.
  925. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  926. NULL,
  927. (string(unsigned_delegation_txt) +
  928. string(unsigned_delegation_nsec_txt) +
  929. string("unsigned-delegation.example.com. 3600 IN RRSIG ") +
  930. getCommonRRSIGText("NSEC")).c_str(),
  931. NULL);
  932. }
  933. TEST_F(QueryTest, badSecureDelegation) {
  934. // Test whether exception is raised if DS query at delegation results in
  935. // something different than SUCCESS or NXRRSET
  936. EXPECT_THROW(Query(memory_client, Name("bad-delegation.example.com"),
  937. qtype, response, true).process(), Query::BadDS);
  938. // But only if DNSSEC is requested (it shouldn't even try to look for
  939. // the DS otherwise)
  940. EXPECT_NO_THROW(Query(memory_client, Name("bad-delegation.example.com"),
  941. qtype, response).process());
  942. }
  943. TEST_F(QueryTest, nxdomain) {
  944. EXPECT_NO_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
  945. response).process());
  946. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 1, 0,
  947. NULL, soa_txt, NULL, mock_finder->getOrigin());
  948. }
  949. TEST_F(QueryTest, nxdomainWithNSEC) {
  950. // NXDOMAIN with DNSSEC proof. We should have SOA, NSEC that proves
  951. // NXDOMAIN and NSEC that proves nonexistence of matching wildcard,
  952. // as well as their RRSIGs.
  953. EXPECT_NO_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
  954. response, true).process());
  955. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  956. NULL, (string(soa_txt) +
  957. string("example.com. 3600 IN RRSIG ") +
  958. getCommonRRSIGText("SOA") + "\n" +
  959. string(nsec_nxdomain_txt) + "\n" +
  960. string("noglue.example.com. 3600 IN RRSIG ") +
  961. getCommonRRSIGText("NSEC") + "\n" +
  962. string(nsec_apex_txt) + "\n" +
  963. string("example.com. 3600 IN RRSIG ") +
  964. getCommonRRSIGText("NSEC")).c_str(),
  965. NULL, mock_finder->getOrigin());
  966. }
  967. TEST_F(QueryTest, nxdomainWithNSEC2) {
  968. // See comments about no_txt. In this case the best possible wildcard
  969. // is derived from the next domain of the NSEC that proves NXDOMAIN, and
  970. // the NSEC to provide the non existence of wildcard is different from
  971. // the first NSEC.
  972. Query(memory_client, Name("(.no.example.com"), qtype,
  973. response, true).process();
  974. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  975. NULL, (string(soa_txt) +
  976. string("example.com. 3600 IN RRSIG ") +
  977. getCommonRRSIGText("SOA") + "\n" +
  978. string(nsec_mx_txt) + "\n" +
  979. string("mx.example.com. 3600 IN RRSIG ") +
  980. getCommonRRSIGText("NSEC") + "\n" +
  981. string(nsec_no_txt) + "\n" +
  982. string(").no.example.com. 3600 IN RRSIG ") +
  983. getCommonRRSIGText("NSEC")).c_str(),
  984. NULL, mock_finder->getOrigin());
  985. }
  986. TEST_F(QueryTest, nxdomainWithNSECDuplicate) {
  987. // See comments about nz_txt. In this case we only need one NSEC,
  988. // which proves both NXDOMAIN and the non existence of wildcard.
  989. Query(memory_client, Name("nx.no.example.com"), qtype,
  990. response, true).process();
  991. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 4, 0,
  992. NULL, (string(soa_txt) +
  993. string("example.com. 3600 IN RRSIG ") +
  994. getCommonRRSIGText("SOA") + "\n" +
  995. string(nsec_no_txt) + "\n" +
  996. string(").no.example.com. 3600 IN RRSIG ") +
  997. getCommonRRSIGText("NSEC")).c_str(),
  998. NULL, mock_finder->getOrigin());
  999. }
  1000. TEST_F(QueryTest, nxdomainBadNSEC1) {
  1001. // ZoneFinder::find() returns NXDOMAIN with non NSEC RR.
  1002. mock_finder->setNSECResult(Name("badnsec.example.com"),
  1003. ZoneFinder::NXDOMAIN,
  1004. mock_finder->delegation_rrset_);
  1005. EXPECT_THROW(Query(memory_client, Name("badnsec.example.com"), qtype,
  1006. response, true).process(),
  1007. std::bad_cast);
  1008. }
  1009. TEST_F(QueryTest, nxdomainBadNSEC2) {
  1010. // ZoneFinder::find() returns NXDOMAIN with an empty NSEC RR.
  1011. mock_finder->setNSECResult(Name("emptynsec.example.com"),
  1012. ZoneFinder::NXDOMAIN,
  1013. mock_finder->empty_nsec_rrset_);
  1014. EXPECT_THROW(Query(memory_client, Name("emptynsec.example.com"), qtype,
  1015. response, true).process(),
  1016. Query::BadNSEC);
  1017. }
  1018. TEST_F(QueryTest, nxdomainBadNSEC3) {
  1019. // "no-wildcard proof" returns SUCCESS. it should be NXDOMAIN.
  1020. mock_finder->setNSECResult(Name("*.example.com"),
  1021. ZoneFinder::SUCCESS,
  1022. mock_finder->delegation_rrset_);
  1023. EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
  1024. response, true).process(),
  1025. Query::BadNSEC);
  1026. }
  1027. TEST_F(QueryTest, nxdomainBadNSEC4) {
  1028. // "no-wildcard proof" doesn't return RRset.
  1029. mock_finder->setNSECResult(Name("*.example.com"),
  1030. ZoneFinder::NXDOMAIN, ConstRRsetPtr());
  1031. EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
  1032. response, true).process(),
  1033. Query::BadNSEC);
  1034. }
  1035. TEST_F(QueryTest, nxdomainBadNSEC5) {
  1036. // "no-wildcard proof" returns non NSEC.
  1037. mock_finder->setNSECResult(Name("*.example.com"),
  1038. ZoneFinder::NXDOMAIN,
  1039. mock_finder->delegation_rrset_);
  1040. // This is a bit odd, but we'll simply include the returned RRset.
  1041. Query(memory_client, Name("nxdomain.example.com"), qtype,
  1042. response, true).process();
  1043. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 8, 0,
  1044. NULL, (string(soa_txt) +
  1045. string("example.com. 3600 IN RRSIG ") +
  1046. getCommonRRSIGText("SOA") + "\n" +
  1047. string(nsec_nxdomain_txt) + "\n" +
  1048. string("noglue.example.com. 3600 IN RRSIG ") +
  1049. getCommonRRSIGText("NSEC") + "\n" +
  1050. delegation_txt).c_str(),
  1051. NULL, mock_finder->getOrigin());
  1052. }
  1053. TEST_F(QueryTest, nxdomainBadNSEC6) {
  1054. // "no-wildcard proof" returns empty NSEC.
  1055. mock_finder->setNSECResult(Name("*.example.com"),
  1056. ZoneFinder::NXDOMAIN,
  1057. mock_finder->empty_nsec_rrset_);
  1058. EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
  1059. response, true).process(),
  1060. Query::BadNSEC);
  1061. }
  1062. TEST_F(QueryTest, nxrrset) {
  1063. EXPECT_NO_THROW(Query(memory_client, Name("www.example.com"),
  1064. RRType::TXT(), response).process());
  1065. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 1, 0,
  1066. NULL, soa_txt, NULL, mock_finder->getOrigin());
  1067. }
  1068. TEST_F(QueryTest, nxrrsetWithNSEC) {
  1069. // NXRRSET with DNSSEC proof. We should have SOA, NSEC that proves the
  1070. // NXRRSET and their RRSIGs.
  1071. Query(memory_client, Name("www.example.com"), RRType::TXT(), response,
  1072. true).process();
  1073. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1074. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1075. getCommonRRSIGText("SOA") + "\n" +
  1076. string(nsec_www_txt) + "\n" +
  1077. string("www.example.com. 3600 IN RRSIG ") +
  1078. getCommonRRSIGText("NSEC")).c_str(),
  1079. NULL, mock_finder->getOrigin());
  1080. }
  1081. TEST_F(QueryTest, emptyNameWithNSEC) {
  1082. // Empty non terminal with DNSSEC proof. This is one of the cases of
  1083. // Section 3.1.3.2 of RFC4035.
  1084. // mx.example.com. NSEC ).no.example.com. proves no.example.com. is a
  1085. // non empty terminal node. Note that it also implicitly proves there
  1086. // should be no closer wildcard match (because the empty name is an
  1087. // exact match), so we only need one NSEC.
  1088. // From the point of the Query::process(), this is actually no different
  1089. // from the other NXRRSET case, but we check that explicitly just in case.
  1090. Query(memory_client, Name("no.example.com"), RRType::A(), response,
  1091. true).process();
  1092. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1093. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1094. getCommonRRSIGText("SOA") + "\n" +
  1095. string(nsec_mx_txt) + "\n" +
  1096. string("mx.example.com. 3600 IN RRSIG ") +
  1097. getCommonRRSIGText("NSEC")).c_str(),
  1098. NULL, mock_finder->getOrigin());
  1099. }
  1100. TEST_F(QueryTest, nxrrsetWithoutNSEC) {
  1101. // NXRRSET with DNSSEC proof requested, but there's no NSEC at that node.
  1102. // This is an unexpected event (if the zone is supposed to be properly
  1103. // signed with NSECs), but we accept and ignore the oddity.
  1104. Query(memory_client, Name("nonsec.example.com"), RRType::TXT(), response,
  1105. true).process();
  1106. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 2, 0, NULL,
  1107. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1108. getCommonRRSIGText("SOA") + "\n").c_str(),
  1109. NULL, mock_finder->getOrigin());
  1110. }
  1111. TEST_F(QueryTest, wildcardNSEC) {
  1112. // The qname matches *.wild.example.com. The response should contain
  1113. // an NSEC that proves the non existence of a closer name.
  1114. Query(memory_client, Name("www.wild.example.com"), RRType::A(), response,
  1115. true).process();
  1116. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 6, 6,
  1117. (string(wild_txt).replace(0, 1, "www") +
  1118. string("www.wild.example.com. 3600 IN RRSIG ") +
  1119. getCommonRRSIGText("A") + "\n").c_str(),
  1120. (zone_ns_txt + string("example.com. 3600 IN RRSIG NS 5 "
  1121. "3 3600 20000101000000 "
  1122. "20000201000000 12345 "
  1123. "example.com. FAKEFAKEFAKE\n") +
  1124. string(nsec_wild_txt) +
  1125. string("*.wild.example.com. 3600 IN RRSIG ") +
  1126. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1127. NULL, // we are not interested in additionals in this test
  1128. mock_finder->getOrigin());
  1129. }
  1130. TEST_F(QueryTest, CNAMEwildNSEC) {
  1131. // Similar to the previous case, but the matching wildcard record is
  1132. // CNAME.
  1133. Query(memory_client, Name("www.cnamewild.example.com"), RRType::A(),
  1134. response, true).process();
  1135. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
  1136. (string(cnamewild_txt).replace(0, 1, "www") +
  1137. string("www.cnamewild.example.com. 3600 IN RRSIG ") +
  1138. getCommonRRSIGText("CNAME") + "\n").c_str(),
  1139. (string(nsec_cnamewild_txt) +
  1140. string("*.cnamewild.example.com. 3600 IN RRSIG ") +
  1141. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1142. NULL, // we are not interested in additionals in this test
  1143. mock_finder->getOrigin());
  1144. }
  1145. TEST_F(QueryTest, badWildcardProof1) {
  1146. // Unexpected case in wildcard proof: ZoneFinder::find() returns SUCCESS
  1147. // when NXDOMAIN is expected.
  1148. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1149. ZoneFinder::SUCCESS,
  1150. mock_finder->delegation_rrset_);
  1151. EXPECT_THROW(Query(memory_client, Name("www.wild.example.com"),
  1152. RRType::A(), response, true).process(),
  1153. Query::BadNSEC);
  1154. }
  1155. TEST_F(QueryTest, badWildcardProof2) {
  1156. // "wildcard proof" doesn't return RRset.
  1157. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1158. ZoneFinder::NXDOMAIN, ConstRRsetPtr());
  1159. EXPECT_THROW(Query(memory_client, Name("www.wild.example.com"),
  1160. RRType::A(), response, true).process(),
  1161. Query::BadNSEC);
  1162. }
  1163. TEST_F(QueryTest, badWildcardProof3) {
  1164. // "wildcard proof" returns empty NSEC.
  1165. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1166. ZoneFinder::NXDOMAIN,
  1167. mock_finder->empty_nsec_rrset_);
  1168. EXPECT_THROW(Query(memory_client, Name("www.wild.example.com"),
  1169. RRType::A(), response, true).process(),
  1170. Query::BadNSEC);
  1171. }
  1172. TEST_F(QueryTest, wildcardNxrrsetWithDuplicateNSEC) {
  1173. // WILDCARD_NXRRSET with DNSSEC proof. We should have SOA, NSEC that proves the
  1174. // NXRRSET and their RRSIGs. In this case we only need one NSEC,
  1175. // which proves both NXDOMAIN and the non existence RRSETs of wildcard.
  1176. Query(memory_client, Name("www.wild.example.com"), RRType::TXT(), response,
  1177. true).process();
  1178. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1179. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1180. getCommonRRSIGText("SOA") + "\n" +
  1181. string(nsec_wild_txt) +
  1182. string("*.wild.example.com. 3600 IN RRSIG ") +
  1183. getCommonRRSIGText("NSEC")+"\n").c_str(),
  1184. NULL, mock_finder->getOrigin());
  1185. }
  1186. TEST_F(QueryTest, wildcardNxrrsetWithNSEC) {
  1187. // WILDCARD_NXRRSET with DNSSEC proof. We should have SOA, NSEC that proves the
  1188. // NXRRSET and their RRSIGs. In this case we need two NSEC RRs,
  1189. // one proves NXDOMAIN and the other proves non existence RRSETs of wildcard.
  1190. Query(memory_client, Name("www1.uwild.example.com"), RRType::TXT(), response,
  1191. true).process();
  1192. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  1193. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1194. getCommonRRSIGText("SOA") + "\n" +
  1195. string(nsec_wild_txt_nxrrset) +
  1196. string("*.uwild.example.com. 3600 IN RRSIG ") +
  1197. getCommonRRSIGText("NSEC")+"\n" +
  1198. string(nsec_wild_txt_next) +
  1199. string("www.uwild.example.com. 3600 IN RRSIG ") +
  1200. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1201. NULL, mock_finder->getOrigin());
  1202. }
  1203. TEST_F(QueryTest, wildcardEmptyWithNSEC) {
  1204. // WILDCARD_EMPTY with DNSSEC proof. We should have SOA, NSEC that proves the
  1205. // NXDOMAIN and their RRSIGs. In this case we need two NSEC RRs,
  1206. // one proves NXDOMAIN and the other proves non existence wildcard.
  1207. Query(memory_client, Name("a.t.example.com"), RRType::A(), response,
  1208. true).process();
  1209. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  1210. (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
  1211. getCommonRRSIGText("SOA") + "\n" +
  1212. string(nsec_empty_prev_txt) +
  1213. string("t.example.com. 3600 IN RRSIG ") +
  1214. getCommonRRSIGText("NSEC")+"\n" +
  1215. string(nsec_empty_txt) +
  1216. string("b.*.t.example.com. 3600 IN RRSIG ") +
  1217. getCommonRRSIGText("NSEC")+"\n").c_str(),
  1218. NULL, mock_finder->getOrigin());
  1219. }
  1220. /*
  1221. * This tests that when there's no SOA and we need a negative answer. It should
  1222. * throw in that case.
  1223. */
  1224. TEST_F(QueryTest, noSOA) {
  1225. // disable zone's SOA RR.
  1226. mock_finder->setSOAFlag(false);
  1227. // The NX Domain
  1228. EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"),
  1229. qtype, response).process(), Query::NoSOA);
  1230. // Of course, we don't look into the response, as it throwed
  1231. // NXRRSET
  1232. EXPECT_THROW(Query(memory_client, Name("nxrrset.example.com"),
  1233. qtype, response).process(), Query::NoSOA);
  1234. }
  1235. TEST_F(QueryTest, noMatchZone) {
  1236. // there's a zone in the memory datasource but it doesn't match the qname.
  1237. // should result in REFUSED.
  1238. Query(memory_client, Name("example.org"), qtype, response).process();
  1239. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  1240. }
  1241. /*
  1242. * Test MX additional processing.
  1243. *
  1244. * The MX RRset has two RRs, one pointing to a known domain with
  1245. * A record, other to unknown out of zone one.
  1246. */
  1247. TEST_F(QueryTest, MX) {
  1248. Query(memory_client, Name("mx.example.com"), RRType::MX(),
  1249. response).process();
  1250. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 3, 3, 4,
  1251. mx_txt, NULL,
  1252. (string(ns_addrs_txt) + string(www_a_txt)).c_str());
  1253. }
  1254. /*
  1255. * Test when we ask for MX whose exchange is an alias (CNAME in this case).
  1256. *
  1257. * This should not trigger the additional processing for the exchange.
  1258. */
  1259. TEST_F(QueryTest, MXAlias) {
  1260. Query(memory_client, Name("cnamemx.example.com"), RRType::MX(),
  1261. response).process();
  1262. // there shouldn't be no additional RRs for the exchanges (we have 3
  1263. // RRs for the NS). The normal MX case is tested separately so we don't
  1264. // bother to examine the answer (and authority) sections.
  1265. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1266. NULL, NULL, ns_addrs_txt);
  1267. }
  1268. /*
  1269. * Tests encountering a cname.
  1270. *
  1271. * There are tests leading to successful answers, NXRRSET, NXDOMAIN and
  1272. * out of the zone.
  1273. *
  1274. * TODO: We currently don't do chaining, so only the CNAME itself should be
  1275. * returned.
  1276. */
  1277. TEST_F(QueryTest, CNAME) {
  1278. Query(memory_client, Name("cname.example.com"), RRType::A(),
  1279. response).process();
  1280. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1281. cname_txt, NULL, NULL);
  1282. }
  1283. TEST_F(QueryTest, explicitCNAME) {
  1284. // same owner name as the CNAME test but explicitly query for CNAME RR.
  1285. // expect the same response as we don't provide a full chain yet.
  1286. Query(memory_client, Name("cname.example.com"), RRType::CNAME(),
  1287. response).process();
  1288. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1289. cname_txt, zone_ns_txt, ns_addrs_txt);
  1290. }
  1291. TEST_F(QueryTest, CNAME_NX_RRSET) {
  1292. // Leads to www.example.com, it doesn't have TXT
  1293. // note: with chaining, what should be expected is not trivial:
  1294. // BIND 9 returns the CNAME in answer and SOA in authority, no additional.
  1295. // NSD returns the CNAME, NS in authority, A/AAAA for NS in additional.
  1296. Query(memory_client, Name("cname.example.com"), RRType::TXT(),
  1297. response).process();
  1298. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1299. cname_txt, NULL, NULL);
  1300. }
  1301. TEST_F(QueryTest, explicitCNAME_NX_RRSET) {
  1302. // same owner name as the NXRRSET test but explicitly query for CNAME RR.
  1303. Query(memory_client, Name("cname.example.com"), RRType::CNAME(),
  1304. response).process();
  1305. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1306. cname_txt, zone_ns_txt, ns_addrs_txt);
  1307. }
  1308. TEST_F(QueryTest, CNAME_NX_DOMAIN) {
  1309. // Leads to nxdomain.example.com
  1310. // note: with chaining, what should be expected is not trivial:
  1311. // BIND 9 returns the CNAME in answer and SOA in authority, no additional,
  1312. // RCODE being NXDOMAIN.
  1313. // NSD returns the CNAME, NS in authority, A/AAAA for NS in additional,
  1314. // RCODE being NOERROR.
  1315. Query(memory_client, Name("cnamenxdom.example.com"), RRType::A(),
  1316. response).process();
  1317. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1318. cname_nxdom_txt, NULL, NULL);
  1319. }
  1320. TEST_F(QueryTest, explicitCNAME_NX_DOMAIN) {
  1321. // same owner name as the NXDOMAIN test but explicitly query for CNAME RR.
  1322. Query(memory_client, Name("cnamenxdom.example.com"), RRType::CNAME(),
  1323. response).process();
  1324. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1325. cname_nxdom_txt, zone_ns_txt, ns_addrs_txt);
  1326. }
  1327. TEST_F(QueryTest, CNAME_OUT) {
  1328. /*
  1329. * This leads out of zone. This should have only the CNAME even
  1330. * when we do chaining.
  1331. *
  1332. * TODO: We should be able to have two zones in the mock data source.
  1333. * Then the same test should be done with .org included there and
  1334. * see what it does (depends on what we want to do)
  1335. */
  1336. Query(memory_client, Name("cnameout.example.com"), RRType::A(),
  1337. response).process();
  1338. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1339. cname_out_txt, NULL, NULL);
  1340. }
  1341. TEST_F(QueryTest, explicitCNAME_OUT) {
  1342. // same owner name as the OUT test but explicitly query for CNAME RR.
  1343. Query(memory_client, Name("cnameout.example.com"), RRType::CNAME(),
  1344. response).process();
  1345. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1346. cname_out_txt, zone_ns_txt, ns_addrs_txt);
  1347. }
  1348. /*
  1349. * Test a query under a domain with DNAME. We should get a synthetized CNAME
  1350. * as well as the DNAME.
  1351. *
  1352. * TODO: Once we have CNAME chaining, check it works with synthetized CNAMEs
  1353. * as well. This includes tests pointing inside the zone, outside the zone,
  1354. * pointing to NXRRSET and NXDOMAIN cases (similarly as with CNAME).
  1355. */
  1356. TEST_F(QueryTest, DNAME) {
  1357. Query(memory_client, Name("www.dname.example.com"), RRType::A(),
  1358. response).process();
  1359. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1360. (string(dname_txt) + synthetized_cname_txt).c_str(),
  1361. NULL, NULL);
  1362. }
  1363. /*
  1364. * Ask an ANY query below a DNAME. Should return the DNAME and synthetized
  1365. * CNAME.
  1366. *
  1367. * ANY is handled specially sometimes. We check it is not the case with
  1368. * DNAME.
  1369. */
  1370. TEST_F(QueryTest, DNAME_ANY) {
  1371. Query(memory_client, Name("www.dname.example.com"), RRType::ANY(),
  1372. response).process();
  1373. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1374. (string(dname_txt) + synthetized_cname_txt).c_str(), NULL, NULL);
  1375. }
  1376. // Test when we ask for DNAME explicitly, it does no synthetizing.
  1377. TEST_F(QueryTest, explicitDNAME) {
  1378. Query(memory_client, Name("dname.example.com"), RRType::DNAME(),
  1379. response).process();
  1380. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1381. dname_txt, zone_ns_txt, ns_addrs_txt);
  1382. }
  1383. /*
  1384. * Request a RRset at the domain with DNAME. It should not synthetize
  1385. * the CNAME, it should return the RRset.
  1386. */
  1387. TEST_F(QueryTest, DNAME_A) {
  1388. Query(memory_client, Name("dname.example.com"), RRType::A(),
  1389. response).process();
  1390. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1391. dname_a_txt, zone_ns_txt, ns_addrs_txt);
  1392. }
  1393. /*
  1394. * Request a RRset at the domain with DNAME that is not there (NXRRSET).
  1395. * It should not synthetize the CNAME.
  1396. */
  1397. TEST_F(QueryTest, DNAME_NX_RRSET) {
  1398. EXPECT_NO_THROW(Query(memory_client, Name("dname.example.com"),
  1399. RRType::TXT(), response).process());
  1400. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 1, 0,
  1401. NULL, soa_txt, NULL, mock_finder->getOrigin());
  1402. }
  1403. /*
  1404. * Constructing the CNAME will result in a name that is too long. This,
  1405. * however, should not throw (and crash the server), but respond with
  1406. * YXDOMAIN.
  1407. */
  1408. TEST_F(QueryTest, LongDNAME) {
  1409. // A name that is as long as it can be
  1410. Name longname(
  1411. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1412. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1413. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1414. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1415. "dname.example.com.");
  1416. EXPECT_NO_THROW(Query(memory_client, longname, RRType::A(),
  1417. response).process());
  1418. responseCheck(response, Rcode::YXDOMAIN(), AA_FLAG, 1, 0, 0,
  1419. dname_txt, NULL, NULL);
  1420. }
  1421. /*
  1422. * Constructing the CNAME will result in a name of maximal length.
  1423. * This tests that we don't reject valid one by some kind of off by
  1424. * one mistake.
  1425. */
  1426. TEST_F(QueryTest, MaxLenDNAME) {
  1427. Name longname(
  1428. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1429. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1430. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1431. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1432. "dname.example.com.");
  1433. EXPECT_NO_THROW(Query(memory_client, longname, RRType::A(),
  1434. response).process());
  1435. // Check the answer is OK
  1436. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1437. NULL, NULL, NULL);
  1438. // Check that the CNAME has the maximal length.
  1439. bool ok(false);
  1440. for (RRsetIterator i(response.beginSection(Message::SECTION_ANSWER));
  1441. i != response.endSection(Message::SECTION_ANSWER); ++ i) {
  1442. if ((*i)->getType() == RRType::CNAME()) {
  1443. ok = true;
  1444. RdataIteratorPtr ci((*i)->getRdataIterator());
  1445. ASSERT_FALSE(ci->isLast()) << "The CNAME is empty";
  1446. /*
  1447. * Does anybody have a clue why, if the Name::MAX_WIRE is put
  1448. * directly inside ASSERT_EQ, it fails to link and complains
  1449. * it is unresolved external?
  1450. */
  1451. const size_t max_len(Name::MAX_WIRE);
  1452. ASSERT_EQ(max_len, dynamic_cast<const rdata::generic::CNAME&>(
  1453. ci->getCurrent()).getCname().getLength());
  1454. }
  1455. }
  1456. EXPECT_TRUE(ok) << "The synthetized CNAME not found";
  1457. }
  1458. // Test for this test module itself
  1459. void
  1460. nsec3Check(bool expected_matched, uint8_t expected_labels,
  1461. const string& expected_rrsets_txt,
  1462. const ZoneFinder::FindNSEC3Result& result)
  1463. {
  1464. vector<ConstRRsetPtr> actual_rrsets;
  1465. EXPECT_EQ(expected_matched, result.matched);
  1466. // Convert to int so the error messages would be more readable:
  1467. EXPECT_EQ(static_cast<int>(expected_labels),
  1468. static_cast<int>(result.closest_labels));
  1469. if (result.closest_proof) {
  1470. actual_rrsets.push_back(result.closest_proof);
  1471. }
  1472. if (result.next_proof) {
  1473. actual_rrsets.push_back(result.next_proof);
  1474. }
  1475. rrsetsCheck(expected_rrsets_txt, actual_rrsets.begin(),
  1476. actual_rrsets.end());
  1477. }
  1478. TEST_F(QueryTest, findNSEC3) {
  1479. // In all test cases in the recursive mode, the closest encloser is the
  1480. // apex, and result's closest_labels should be the number of apex labels.
  1481. // (In non recursive mode closest_labels should be the # labels of the
  1482. // query name)
  1483. const uint8_t expected_closest_labels =
  1484. Name("example.com").getLabelCount();
  1485. // Apex name. It should have a matching NSEC3
  1486. nsec3Check(true, expected_closest_labels, nsec3_apex_txt,
  1487. mock_finder->findNSEC3(Name("example.com"), false));
  1488. // Recursive mode doesn't change the result in this case.
  1489. nsec3Check(true, expected_closest_labels, nsec3_apex_txt,
  1490. mock_finder->findNSEC3(Name("example.com"), true));
  1491. // Non existent name. Disabling recursion, a covering NSEC3 should be
  1492. // returned.
  1493. nsec3Check(false, 4, nsec3_www_txt,
  1494. mock_finder->findNSEC3(Name("nxdomain.example.com"), false));
  1495. // Non existent name. The closest provable encloser is the apex,
  1496. // and next closer is the query name.
  1497. nsec3Check(true, expected_closest_labels,
  1498. string(nsec3_apex_txt) + string(nsec3_www_txt),
  1499. mock_finder->findNSEC3(Name("nxdomain.example.com"), true));
  1500. // Similar to the previous case, but next closer name is different
  1501. // (is the parent) of the non existent name.
  1502. nsec3Check(true, expected_closest_labels,
  1503. string(nsec3_apex_txt) + string(nsec3_www_txt),
  1504. mock_finder->findNSEC3(Name("nx.domain.example.com"), true));
  1505. // In the rest of test we check hash comparison for wrap around cases.
  1506. nsec3Check(false, 4, nsec3_apex_txt,
  1507. mock_finder->findNSEC3(Name("nxdomain2.example.com"), false));
  1508. nsec3Check(false, 4, nsec3_www_txt,
  1509. mock_finder->findNSEC3(Name("nxdomain3.example.com"), false));
  1510. }
  1511. TEST_F(QueryTest, nxdomainWithBadNextNSEC3Proof) {
  1512. mock_finder->setNSEC3Flag(true);
  1513. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  1514. ConstRRsetPtr());
  1515. mock_finder->setNSEC3Result(&nsec3);
  1516. EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"),
  1517. RRType::TXT(), response, true).process(),
  1518. Query::BadNSEC3);
  1519. }
  1520. TEST_F(QueryTest, nxdomainWithNSEC3Proof) {
  1521. mock_finder->setNSEC3Flag(true);
  1522. Query(memory_client, Name("nxdomain.example.com"), qtype,
  1523. response, true).process();
  1524. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  1525. NULL, (string(soa_txt) +
  1526. string("example.com. 3600 IN RRSIG ") +
  1527. getCommonRRSIGText("SOA") + "\n" +
  1528. string(nsec3_apex_txt) + "\n" +
  1529. string("0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example.com. 3600 IN RRSIG ") +
  1530. getCommonRRSIGText("NSEC3") + "\n" +
  1531. string(nsec3_www_txt) + "\n" +
  1532. string("q04jkcevqvmu85r014c7dkba38o0ji5r.example.com. 3600 IN RRSIG ") +
  1533. getCommonRRSIGText("NSEC3")).c_str(),
  1534. NULL, mock_finder->getOrigin());
  1535. }
  1536. // The following are tentative tests until we really add tests for the
  1537. // query logic for these cases. At that point it's probably better to
  1538. // clean them up.
  1539. TEST_F(QueryTest, nxrrsetWithNSEC3) {
  1540. mock_finder->setNSEC3Flag(true);
  1541. ZoneFinder::FindResult result = mock_finder->find(
  1542. Name("www.example.com"), RRType::TXT(), ZoneFinder::FIND_DNSSEC);
  1543. EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
  1544. EXPECT_FALSE(result.rrset);
  1545. EXPECT_TRUE(result.isNSEC3Signed());
  1546. EXPECT_FALSE(result.isWildcard());
  1547. }
  1548. TEST_F(QueryTest, emptyNameWithNSEC3) {
  1549. mock_finder->setNSEC3Flag(true);
  1550. ZoneFinder::FindResult result = mock_finder->find(
  1551. Name("no.example.com"), RRType::A(), ZoneFinder::FIND_DNSSEC);
  1552. EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
  1553. EXPECT_FALSE(result.rrset);
  1554. EXPECT_TRUE(result.isNSEC3Signed());
  1555. EXPECT_FALSE(result.isWildcard());
  1556. }
  1557. TEST_F(QueryTest, wildcardNxrrsetWithNSEC3) {
  1558. mock_finder->setNSEC3Flag(true);
  1559. ZoneFinder::FindResult result = mock_finder->find(
  1560. Name("www1.uwild.example.com"), RRType::TXT(),
  1561. ZoneFinder::FIND_DNSSEC);
  1562. EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
  1563. EXPECT_FALSE(result.rrset);
  1564. EXPECT_TRUE(result.isNSEC3Signed());
  1565. EXPECT_TRUE(result.isWildcard());
  1566. }
  1567. TEST_F(QueryTest, wildcardEmptyWithNSEC3) {
  1568. mock_finder->setNSEC3Flag(true);
  1569. ZoneFinder::FindResult result = mock_finder->find(
  1570. Name("a.t.example.com"), RRType::A(), ZoneFinder::FIND_DNSSEC);
  1571. EXPECT_EQ(ZoneFinder::NXRRSET, result.code);
  1572. EXPECT_TRUE(result.isNSEC3Signed());
  1573. EXPECT_TRUE(result.isWildcard());
  1574. }
  1575. }