query_unittest.cc 72 KB

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