query_unittest.cc 121 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863
  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 <boost/bind.hpp>
  15. #include <boost/scoped_ptr.hpp>
  16. #include <boost/static_assert.hpp>
  17. #include <exceptions/exceptions.h>
  18. #include <dns/masterload.h>
  19. #include <dns/message.h>
  20. #include <dns/master_loader.h>
  21. #include <dns/name.h>
  22. #include <dns/labelsequence.h>
  23. #include <dns/nsec3hash.h>
  24. #include <dns/opcode.h>
  25. #include <dns/rcode.h>
  26. #include <dns/rrcollator.h>
  27. #include <dns/rrttl.h>
  28. #include <dns/rrtype.h>
  29. #include <dns/rdataclass.h>
  30. #include <datasrc/client.h>
  31. #include <datasrc/client_list.h>
  32. #include <auth/query.h>
  33. #include <testutils/dnsmessage_test.h>
  34. #include <gtest/gtest.h>
  35. #include <cstdlib>
  36. #include <fstream>
  37. #include <map>
  38. #include <sstream>
  39. #include <vector>
  40. using namespace std;
  41. using namespace isc::dns;
  42. using namespace isc::dns::rdata;
  43. using namespace isc::datasrc;
  44. using namespace isc::auth;
  45. using namespace isc::testutils;
  46. namespace {
  47. // Simple wrapper for a single data source client.
  48. // The list simply delegates all the answers to the single
  49. // client.
  50. class SingletonList : public ClientList {
  51. public:
  52. SingletonList(DataSourceClient& client) :
  53. client_(client)
  54. {}
  55. virtual FindResult find(const Name& zone, bool exact, bool) const {
  56. DataSourceClient::FindResult result(client_.findZone(zone));
  57. // We don't complicate the tests with real life keepers, but we
  58. // need to put something to the parameter anyway.
  59. const boost::shared_ptr<ClientList::FindResult::LifeKeeper> keeper;
  60. switch (result.code) {
  61. case result::SUCCESS:
  62. return (FindResult(&client_, result.zone_finder, true,
  63. keeper));
  64. case result::PARTIALMATCH:
  65. if (!exact) {
  66. return (FindResult(&client_, result.zone_finder, false,
  67. keeper));
  68. }
  69. default:
  70. return (FindResult());
  71. }
  72. }
  73. virtual ConstZoneTableAccessorPtr
  74. getZoneTableAccessor(const std::string&, bool) const {
  75. isc_throw(isc::NotImplemented,
  76. "getZoneTableAccessor not implemented for SingletonList");
  77. }
  78. private:
  79. DataSourceClient& client_;
  80. };
  81. // These are commonly used data (auto-generated). There are some exceptional
  82. // data that are only used in a limited scenario, which are defined separately
  83. // below.
  84. #include <auth/tests/example_base_inc.cc>
  85. #include <auth/tests/example_nsec3_inc.cc>
  86. // This SOA is used in negative responses; its RRTTL is set to SOA's MINTTL
  87. const char* const soa_minttl_txt =
  88. "example.com. 0 IN SOA . . 1 0 0 0 0\n";
  89. // This is used only in one pathological test case.
  90. const char* const zone_ds_txt =
  91. "example.com. 3600 IN DS 57855 5 1 "
  92. "B6DCD485719ADCA18E5F3D48A2331627FDD3 636B\n";
  93. // This is not inside the zone, this is created at runtime
  94. const char* const synthetized_cname_txt =
  95. "www.dname.example.com. 3600 IN CNAME "
  96. "www.somethinglong.dnametarget.example.com.\n";
  97. // NSEC3 for wild.example.com (used in wildcard tests, will be added on
  98. // demand not to confuse other tests)
  99. const char* const nsec3_atwild_txt =
  100. "ji6neoaepv8b5o6k4ev33abha8ht9fgc.example.com. 3600 IN NSEC3 1 1 12 "
  101. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en\n";
  102. // NSEC3 for cnamewild.example.com (used in wildcard tests, will be added on
  103. // demand not to confuse other tests)
  104. const char* const nsec3_atcnamewild_txt =
  105. "k8udemvp1j2f7eg6jebps17vp3n8i58h.example.com. 3600 IN NSEC3 1 1 12 "
  106. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en\n";
  107. // NSEC3 for *.uwild.example.com (will be added on demand not to confuse
  108. // other tests)
  109. const char* const nsec3_wild_txt =
  110. "b4um86eghhds6nea196smvmlo4ors995.example.com. 3600 IN NSEC3 1 1 12 "
  111. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG\n";
  112. // NSEC3 for uwild.example.com. (will be added on demand)
  113. const char* const nsec3_uwild_txt =
  114. "t644ebqk9bibcna874givr6joj62mlhv.example.com. 3600 IN NSEC3 1 1 12 "
  115. "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG\n";
  116. // (Secure) delegation data; Delegation without DS record (and both NSEC
  117. // and NSEC3 denying its existence)
  118. // This one will be added on demand
  119. const char* const unsigned_delegation_nsec3_txt =
  120. "q81r598950igr1eqvc60aedlq66425b5.example.com. 3600 IN NSEC3 1 1 12 "
  121. "aabbccdd 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom NS RRSIG\n";
  122. // Name of an "empty" zone: used to simulate the case of
  123. // configured-but-available zone (due to load errors, etc).
  124. // Each tested data source client is expected to have this zone (SQLite3
  125. // currently doesn't have this concept so it's skipped)
  126. const char* const EMPTY_ZONE_NAME = "empty.example.org";
  127. // A helper function that generates a textual representation of RRSIG RDATA
  128. // for the given covered type. The resulting RRSIG may not necessarily make
  129. // sense in terms of the DNSSEC protocol, but for our testing purposes it's
  130. // okay.
  131. string
  132. getCommonRRSIGText(const string& type) {
  133. return (type +
  134. string(" 5 3 3600 20000101000000 20000201000000 12345 "
  135. "example.com. FAKEFAKEFAKE"));
  136. }
  137. // A helper callback of masterLoad() used in InMemoryZoneFinderTest.
  138. void
  139. setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
  140. *(*it) = rrset;
  141. ++it;
  142. }
  143. // A helper function that converts a textual form of a single RR into a
  144. // RRsetPtr object. If it's SOA, origin must be set to its owner name;
  145. // otherwise masterLoad() will reject it.
  146. RRsetPtr
  147. textToRRset(const string& text_rrset, const Name& origin = Name::ROOT_NAME()) {
  148. stringstream ss(text_rrset);
  149. RRsetPtr rrset;
  150. vector<RRsetPtr*> rrsets;
  151. rrsets.push_back(&rrset);
  152. masterLoad(ss, origin, RRClass::IN(),
  153. boost::bind(setRRset, _1, rrsets.begin()));
  154. return (rrset);
  155. }
  156. // Setup for faked NSEC3 hash used throughout this test.
  157. class TestNSEC3Hash : public NSEC3Hash {
  158. private:
  159. typedef map<Name, string> NSEC3HashMap;
  160. typedef NSEC3HashMap::value_type NSEC3HashPair;
  161. NSEC3HashMap hash_map_;
  162. public:
  163. TestNSEC3Hash() {
  164. // (Faked) NSEC3 hash map. For convenience we use hardcoded built-in
  165. // map instead of calculating and using actual hash.
  166. // The used hash values are borrowed from RFC5155 examples (they are
  167. // based on the query name, not that they would correspond directly
  168. // to the name).
  169. hash_map_[Name("example.com")] = "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom";
  170. hash_map_[Name("www.example.com")] =
  171. "q04jkcevqvmu85r014c7dkba38o0ji5r";
  172. hash_map_[Name("nxdomain.example.com")] =
  173. "v644ebqk9bibcna874givr6joj62mlhv";
  174. hash_map_[Name("nx.domain.example.com")] =
  175. "v644ebqk9bibcna874givr6joj62mlhv";
  176. hash_map_[Name("domain.example.com")] =
  177. "v644ebqk9bibcna874givr6joj62mlhv";
  178. hash_map_[Name("nxdomain2.example.com")] =
  179. "q00jkcevqvmu85r014c7dkba38o0ji5r";
  180. hash_map_[Name("nxdomain3.example.com")] =
  181. "009mhaveqvm6t7vbl5lop2u3t2rp3tom";
  182. hash_map_[Name("*.example.com")] =
  183. "r53bq7cc2uvmubfu5ocmm6pers9tk9en";
  184. hash_map_[Name("unsigned-delegation.example.com")] =
  185. "q81r598950igr1eqvc60aedlq66425b5"; // a bit larger than H(www)
  186. hash_map_[Name("*.uwild.example.com")] =
  187. "b4um86eghhds6nea196smvmlo4ors995";
  188. hash_map_[Name("unsigned-delegation-optout.example.com")] =
  189. "vld46lphhasfapj8og1pglgiasa5o5gt";
  190. // For wildcard proofs
  191. hash_map_[Name("wild.example.com")] =
  192. "ji6neoaepv8b5o6k4ev33abha8ht9fgc";
  193. hash_map_[Name("y.wild.example.com")] =
  194. "0p9mhaveqvm6t7vbl5lop2u3t2rp3ton"; // a bit larger than H(<apex>)
  195. hash_map_[Name("x.y.wild.example.com")] =
  196. "q04jkcevqvmu85r014c7dkba38o0ji6r"; // a bit larger than H(www)
  197. hash_map_[Name("cnamewild.example.com")] =
  198. "k8udemvp1j2f7eg6jebps17vp3n8i58h";
  199. hash_map_[Name("www.cnamewild.example.com")] =
  200. "q04jkcevqvmu85r014c7dkba38o0ji6r"; // a bit larger than H(www)
  201. // For closest encloser proof for www1.uwild.example.com:
  202. hash_map_[Name("uwild.example.com")] =
  203. "t644ebqk9bibcna874givr6joj62mlhv";
  204. hash_map_[Name("www1.uwild.example.com")] =
  205. "q04jkcevqvmu85r014c7dkba38o0ji6r"; // a bit larger than H(www)
  206. // For empty-non-terminal derived from insecure delegation (we don't
  207. // need a hash for the delegation point itself for that test). the
  208. // hash for empty name is the same as that for unsigned-delegation
  209. // above, as the case is similar to that.
  210. hash_map_[Name("empty.example.com")] =
  211. "q81r598950igr1eqvc60aedlq66425b5"; // a bit larger than H(www)
  212. }
  213. virtual string calculate(const Name& name) const {
  214. const NSEC3HashMap::const_iterator found = hash_map_.find(name);
  215. if (found != hash_map_.end()) {
  216. return (found->second);
  217. }
  218. isc_throw(isc::Unexpected, "unexpected name for NSEC3 test: "
  219. << name);
  220. }
  221. virtual string calculate(const LabelSequence& ls) const {
  222. assert(ls.isAbsolute());
  223. // This is not very optimal, but it's only going to be used in
  224. // tests.
  225. const Name name(ls.toText());
  226. return (calculate(name));
  227. }
  228. virtual bool match(const rdata::generic::NSEC3PARAM&) const {
  229. return (true);
  230. }
  231. virtual bool match(const rdata::generic::NSEC3&) const {
  232. return (true);
  233. }
  234. };
  235. class TestNSEC3HashCreator : public isc::dns::NSEC3HashCreator {
  236. public:
  237. TestNSEC3HashCreator() {}
  238. virtual isc::dns::NSEC3Hash*
  239. create(const isc::dns::rdata::generic::NSEC3PARAM&) const {
  240. return (new TestNSEC3Hash);
  241. }
  242. virtual isc::dns::NSEC3Hash*
  243. create(const isc::dns::rdata::generic::NSEC3&) const {
  244. return (new TestNSEC3Hash);
  245. }
  246. virtual isc::dns::NSEC3Hash*
  247. create(uint8_t, uint16_t, const uint8_t*, size_t) const {
  248. return (new TestNSEC3Hash);
  249. }
  250. };
  251. // This is a mock Zone Finder class for testing.
  252. // It is a derived class of ZoneFinder for the convenient of tests.
  253. // Its find() method emulates the common behavior of protocol compliant
  254. // ZoneFinder classes, but simplifies some minor cases and also supports broken
  255. // behavior.
  256. // For simplicity, most names are assumed to be "in zone"; delegations
  257. // to child zones are identified by the existence of non origin NS records.
  258. // Another special name is "dname.example.com". Query names under this name
  259. // will result in DNAME.
  260. class MockZoneFinder : public ZoneFinder {
  261. public:
  262. MockZoneFinder() :
  263. origin_(Name("example.com")),
  264. bad_signed_delegation_name_("bad-delegation.example.com"),
  265. dname_name_("dname.example.com"),
  266. has_SOA_(true),
  267. has_apex_NS_(true),
  268. rrclass_(RRClass::IN()),
  269. include_rrsig_anyway_(false),
  270. use_nsec3_(false),
  271. nsec_name_(origin_),
  272. nsec3_fake_(NULL),
  273. nsec3_name_(NULL)
  274. {
  275. RRCollator collator(boost::bind(&MockZoneFinder::loadRRset, this, _1));
  276. MasterLoader loader(TEST_OWN_DATA_BUILDDIR "/example-nsec3.zone",
  277. origin_, rrclass_,
  278. MasterLoaderCallbacks::getNullCallbacks(),
  279. collator.getCallback());
  280. loader.load();
  281. empty_nsec_rrset_ = ConstRRsetPtr(new RRset(Name::ROOT_NAME(),
  282. RRClass::IN(),
  283. RRType::NSEC(),
  284. RRTTL(3600)));
  285. }
  286. virtual isc::dns::Name getOrigin() const { return (origin_); }
  287. virtual isc::dns::RRClass getClass() const { return (rrclass_); }
  288. virtual ZoneFinderContextPtr find(const isc::dns::Name& name,
  289. const isc::dns::RRType& type,
  290. const FindOptions options =
  291. FIND_DEFAULT);
  292. virtual ZoneFinderContextPtr findAll(const isc::dns::Name& name,
  293. std::vector<ConstRRsetPtr>& target,
  294. const FindOptions options =
  295. FIND_DEFAULT);
  296. virtual ZoneFinder::FindNSEC3Result
  297. findNSEC3(const Name& name, bool recursive);
  298. // If false is passed, it makes the zone broken as if it didn't have the
  299. // SOA.
  300. void setSOAFlag(bool on) { has_SOA_ = on; }
  301. // If false is passed, it makes the zone broken as if it didn't have
  302. // the apex NS.
  303. void setApexNSFlag(bool on) { has_apex_NS_ = on; }
  304. // Turn this on if you want it to return RRSIGs regardless of FIND_GLUE_OK
  305. void setIncludeRRSIGAnyway(bool on) { include_rrsig_anyway_ = on; }
  306. // Once called, this "faked" result will be returned when NSEC is expected
  307. // for the specified query name.
  308. void setNSECResult(const Name& nsec_name, Result code,
  309. ConstRRsetPtr rrset)
  310. {
  311. nsec_name_ = nsec_name;
  312. nsec_context_.reset(
  313. new GenericContext(*this, FIND_DEFAULT, // a fake value
  314. ResultContext(code, rrset, RESULT_NSEC_SIGNED)));
  315. }
  316. // Once called, the findNSEC3 will return the provided result for the next
  317. // query. After that, it'll return to operate normally.
  318. // NULL disables. Does not take ownership of the pointer (it is generally
  319. // expected to be a local variable in the test function).
  320. void setNSEC3Result(const FindNSEC3Result* result,
  321. const Name* name = NULL)
  322. {
  323. nsec3_fake_ = result;
  324. nsec3_name_ = name;
  325. }
  326. // If true is passed return an empty NSEC3 RRset for some negative
  327. // answers when DNSSEC is required.
  328. void setNSEC3Flag(bool on) { use_nsec3_ = on; }
  329. // This method allows tests to insert new record in the middle of the test.
  330. //
  331. // \param record_txt textual RR representation of RR (such as soa_txt, etc)
  332. void addRecord(const string& record_txt) {
  333. stringstream record_stream;
  334. record_stream << record_txt;
  335. masterLoad(record_stream, origin_, rrclass_,
  336. boost::bind(&MockZoneFinder::loadRRset, this, _1));
  337. }
  338. public:
  339. // We allow the tests to use these for convenience
  340. ConstRRsetPtr dname_rrset_; // could be used as an arbitrary bogus RRset
  341. ConstRRsetPtr empty_nsec_rrset_;
  342. protected:
  343. // A convenient shortcut. Will also be used by further derived mocks.
  344. ZoneFinderContextPtr createContext(FindOptions options,
  345. Result code,
  346. isc::dns::ConstRRsetPtr rrset,
  347. FindResultFlags flags = RESULT_DEFAULT)
  348. {
  349. ConstRRsetPtr rp = stripRRsigs(rrset, options);
  350. return (ZoneFinderContextPtr(
  351. new GenericContext(*this, options,
  352. ResultContext(code, rp, flags))));
  353. }
  354. private:
  355. typedef map<RRType, ConstRRsetPtr> RRsetStore;
  356. typedef map<Name, RRsetStore> Domains;
  357. Domains domains_;
  358. Domains delegations_;
  359. Domains nsec3_domains_;
  360. // This is used to identify delegation to a child zone, and used to
  361. // find a matching entry in delegations_. Note that first found entry
  362. // is returned, so it's not a longest match. Test data must be set up
  363. // to ensure the first match is always the longest match.
  364. struct SubdomainMatch {
  365. SubdomainMatch(const Name& name) : name_(name) {}
  366. bool operator()(const pair<Name, RRsetStore>& domain_elem) const {
  367. return (name_ == domain_elem.first ||
  368. name_.compare(domain_elem.first).getRelation() ==
  369. NameComparisonResult::SUBDOMAIN);
  370. }
  371. private:
  372. const Name& name_;
  373. };
  374. void loadRRset(RRsetPtr rrset) {
  375. // For simplicity we dynamically generate RRSIGs and add them below.
  376. // The RRSIG RDATA should be consistent with that defined in the
  377. // zone file.
  378. if (rrset->getType() == RRType::RRSIG()) {
  379. return;
  380. }
  381. // NSEC3PARAM is not used in the mock data source (and it would confuse
  382. // non-NSEC3 test cases).
  383. if (rrset->getType() == RRType::NSEC3PARAM()) {
  384. return;
  385. }
  386. if (rrset->getType() == RRType::NSEC3()) {
  387. // NSEC3 should go to the dedicated table
  388. nsec3_domains_[rrset->getName()][rrset->getType()] = rrset;
  389. // By nature it should have RRSIG. (We may want to selectively
  390. // omit this to test pathological cases).
  391. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  392. getCommonRRSIGText(rrset->getType().
  393. toText()))));
  394. return;
  395. }
  396. domains_[rrset->getName()][rrset->getType()] = rrset;
  397. // Remember delegation (NS/DNAME) related RRsets separately.
  398. if (rrset->getType() == RRType::NS() && rrset->getName() != origin_) {
  399. delegations_[rrset->getName()][rrset->getType()] = rrset;
  400. } else if (rrset->getName() == dname_name_ &&
  401. rrset->getType() == RRType::DNAME()) {
  402. dname_rrset_ = rrset;
  403. }
  404. // Add some signatures. For NS, we only have RRSIG for the origin
  405. // name. For others generate RRSIG unconditionally. Technically this
  406. // is wrong because we shouldn't have it for names under a zone
  407. // cut. But in our tests that doesn't matter, so we add them
  408. // just for simplicity.
  409. // Note that this includes RRSIG for DS with secure delegations.
  410. // They should have RRSIGs, so that's actually expected data, not just
  411. // for simplicity.
  412. if (rrset->getType() != RRType::NS() || rrset->getName() == origin_) {
  413. rrset->addRRsig(RdataPtr(new generic::RRSIG(
  414. getCommonRRSIGText(rrset->getType().
  415. toText()))));
  416. }
  417. }
  418. const Name origin_;
  419. // Names where we delegate somewhere else
  420. const Name bad_signed_delegation_name_;
  421. const Name dname_name_;
  422. bool has_SOA_;
  423. bool has_apex_NS_;
  424. const RRClass rrclass_;
  425. bool include_rrsig_anyway_;
  426. bool use_nsec3_;
  427. // The following two will be used for faked NSEC cases
  428. Name nsec_name_;
  429. ZoneFinderContextPtr nsec_context_;
  430. // The following two are for faking bad NSEC3 responses
  431. // Enabled when not NULL
  432. const FindNSEC3Result* nsec3_fake_;
  433. const Name* nsec3_name_;
  434. TestNSEC3Hash nsec3_hash_;
  435. };
  436. // A helper function that generates a new RRset based on "wild_rrset",
  437. // replacing its owner name with 'real_name'.
  438. ConstRRsetPtr
  439. substituteWild(const AbstractRRset& wild_rrset, const Name& real_name) {
  440. RRsetPtr rrset(new RRset(real_name, wild_rrset.getClass(),
  441. wild_rrset.getType(), wild_rrset.getTTL()));
  442. // For simplicity we only consider the case with one RDATA (for now)
  443. rrset->addRdata(wild_rrset.getRdataIterator()->getCurrent());
  444. ConstRRsetPtr wild_sig = wild_rrset.getRRsig();
  445. if (wild_sig) {
  446. RRsetPtr sig(new RRset(real_name, wild_sig->getClass(),
  447. wild_sig->getType(), wild_sig->getTTL()));
  448. sig->addRdata(wild_sig->getRdataIterator()->getCurrent());
  449. rrset->addRRsig(sig);
  450. }
  451. return (rrset);
  452. }
  453. ZoneFinderContextPtr
  454. MockZoneFinder::findAll(const Name& name, std::vector<ConstRRsetPtr>& target,
  455. const FindOptions options)
  456. {
  457. ZoneFinderContextPtr result(find(name, RRType::ANY(), options));
  458. if (result->code == NXRRSET) {
  459. const Domains::const_iterator found_domain = domains_.find(name);
  460. if (!found_domain->second.empty()) {
  461. for (RRsetStore::const_iterator found_rrset =
  462. found_domain->second.begin();
  463. found_rrset != found_domain->second.end(); ++found_rrset) {
  464. // Insert RRs under the domain name into target
  465. target.push_back(stripRRsigs(found_rrset->second, options));
  466. }
  467. return (ZoneFinderContextPtr(
  468. new GenericContext(*this, options,
  469. ResultContext(SUCCESS, RRsetPtr()),
  470. target)));
  471. }
  472. }
  473. return (result);
  474. }
  475. ZoneFinder::FindNSEC3Result
  476. MockZoneFinder::findNSEC3(const Name& name, bool recursive) {
  477. // Do we have a fake result set? If so, use it.
  478. if (nsec3_fake_ != NULL &&
  479. (nsec3_name_ == NULL || *nsec3_name_ == name)) {
  480. const FindNSEC3Result* result(nsec3_fake_);
  481. return (*result);
  482. }
  483. ConstRRsetPtr covering_proof;
  484. const int labels = name.getLabelCount();
  485. // For brevity, we assume several things below: maps should have an
  486. // expected entry when operator[] is used; maps are not empty.
  487. for (int i = 0; i < labels; ++i) {
  488. const string hlabel = nsec3_hash_.calculate(name.split(i, labels - i));
  489. const Name hname = Name(hlabel + ".example.com");
  490. // We don't use const_iterator so that we can use operator[] below
  491. Domains::iterator found_domain = nsec3_domains_.lower_bound(hname);
  492. // If the given hash is larger than the largest stored hash or
  493. // the first label doesn't match the target, identify the "previous"
  494. // hash value and remember it as the candidate next closer proof.
  495. if (found_domain == nsec3_domains_.end() ||
  496. found_domain->first.split(0, 1).toText(true) != hlabel) {
  497. // If the given hash is larger or smaller than everything,
  498. // the covering proof is the NSEC3 that has the largest hash.
  499. if (found_domain == nsec3_domains_.end() ||
  500. found_domain == nsec3_domains_.begin()) {
  501. covering_proof =
  502. nsec3_domains_.rbegin()->second[RRType::NSEC3()];
  503. } else {
  504. // Otherwise, H(found_domain-1) < given_hash < H(found_domain)
  505. // The covering proof is the first one.
  506. covering_proof = (--found_domain)->second[RRType::NSEC3()];
  507. }
  508. if (!recursive) { // in non recursive mode, we are done.
  509. return (ZoneFinder::FindNSEC3Result(false,
  510. name.getLabelCount(),
  511. covering_proof,
  512. ConstRRsetPtr()));
  513. }
  514. } else { // exact match
  515. return (ZoneFinder::FindNSEC3Result(
  516. true, name.getLabelCount() - i,
  517. found_domain->second[RRType::NSEC3()],
  518. covering_proof));
  519. }
  520. }
  521. isc_throw(isc::Unexpected, "findNSEC3() isn't expected to fail");
  522. }
  523. ZoneFinderContextPtr
  524. MockZoneFinder::find(const Name& name, const RRType& type,
  525. const FindOptions options)
  526. {
  527. // Emulating a broken zone: mandatory apex RRs are missing if specifically
  528. // configured so (which are rare cases).
  529. if (name == origin_ && type == RRType::SOA() && !has_SOA_) {
  530. return (createContext(options, NXDOMAIN, RRsetPtr()));
  531. } else if (name == origin_ && type == RRType::NS() && !has_apex_NS_) {
  532. return (createContext(options, NXDOMAIN, RRsetPtr()));
  533. }
  534. // Special case for names on or under a zone cut and under DNAME
  535. Domains::iterator it;
  536. if ((options & FIND_GLUE_OK) == 0 &&
  537. (it = find_if(delegations_.begin(), delegations_.end(),
  538. SubdomainMatch(name))) != delegations_.end()) {
  539. ConstRRsetPtr delegation_ns = it->second[RRType::NS()];
  540. assert(delegation_ns); // should be ensured by how we construct it
  541. // DS query for the delegated domain (i.e. an exact match) will be
  542. // handled just like an in-zone case below. Others result in
  543. // DELEGATION.
  544. if (type != RRType::DS() || it->first != name) {
  545. return (createContext(options, DELEGATION, delegation_ns));
  546. }
  547. } else if (name.compare(dname_name_).getRelation() ==
  548. NameComparisonResult::SUBDOMAIN) {
  549. return (createContext(options, DNAME, dname_rrset_));
  550. }
  551. // normal cases. names are searched for only per exact-match basis
  552. // for simplicity.
  553. const Domains::const_iterator found_domain = domains_.find(name);
  554. if (found_domain != domains_.end()) {
  555. // First, try exact match.
  556. RRsetStore::const_iterator found_rrset =
  557. found_domain->second.find(type);
  558. if (found_rrset != found_domain->second.end()) {
  559. ConstRRsetPtr rrset = ZoneFinder::stripRRsigs(found_rrset->second,
  560. options);
  561. return (createContext(options, SUCCESS, rrset));
  562. }
  563. // Otherwise, if this domain name has CNAME, return it.
  564. found_rrset = found_domain->second.find(RRType::CNAME());
  565. if (found_rrset != found_domain->second.end()) {
  566. return (createContext(options, CNAME, found_rrset->second));
  567. }
  568. // Otherwise it's NXRRSET case...
  569. // ...but a special pathological case first:
  570. if (found_domain->first == bad_signed_delegation_name_ &&
  571. type == RRType::DS()) {
  572. return (createContext(options, NXDOMAIN, RRsetPtr()));
  573. }
  574. // normal cases follow.
  575. if ((options & FIND_DNSSEC) != 0) {
  576. if (use_nsec3_) {
  577. return (createContext(options, NXRRSET, RRsetPtr(),
  578. RESULT_NSEC3_SIGNED));
  579. }
  580. found_rrset = found_domain->second.find(RRType::NSEC());
  581. if (found_rrset != found_domain->second.end()) {
  582. return (createContext(options, NXRRSET, found_rrset->second,
  583. RESULT_NSEC_SIGNED));
  584. }
  585. }
  586. // If no NSEC is found or DNSSEC isn't specified, behave as if the
  587. // zone is unsigned.
  588. return (createContext(options, NXRRSET, RRsetPtr()));
  589. }
  590. // query name isn't found in our domains.
  591. // We first check if the query name is an empty non terminal name
  592. // of the zone by naive linear search.
  593. Domains::const_iterator domain;
  594. for (domain = domains_.begin(); domain != domains_.end(); ++domain) {
  595. if (name.compare((*domain).first).getRelation() ==
  596. NameComparisonResult::SUPERDOMAIN) {
  597. break;
  598. }
  599. }
  600. if (domain != domains_.end()) {
  601. // The query name is in an empty non terminal node followed by 'domain'
  602. // (for simplicity we ignore the pathological case of 'domain' is
  603. // the origin of the zone)
  604. --domain; // reset domain to the "previous name"
  605. if ((options & FIND_DNSSEC) != 0) {
  606. if (use_nsec3_) {
  607. return (createContext(options, NXRRSET, RRsetPtr(),
  608. RESULT_NSEC3_SIGNED));
  609. }
  610. RRsetStore::const_iterator found_rrset =
  611. (*domain).second.find(RRType::NSEC());
  612. if (found_rrset != (*domain).second.end()) {
  613. return (createContext(options, NXRRSET, found_rrset->second,
  614. RESULT_NSEC_SIGNED));
  615. }
  616. }
  617. return (createContext(options, NXRRSET, RRsetPtr()));
  618. }
  619. // Another possibility is wildcard. For simplicity we only check
  620. // hardcoded specific cases, ignoring other details such as canceling
  621. // due to the existence of closer name.
  622. if ((options & NO_WILDCARD) == 0) {
  623. const Name wild_suffix(name == Name("x.y.wild.example.com") ?
  624. Name("wild.example.com") : name.split(1));
  625. // Unit Tests use those domains for Wildcard test.
  626. if (name.equals(Name("www.wild.example.com")) ||
  627. name.equals(Name("x.y.wild.example.com")) ||
  628. name.equals(Name("www1.uwild.example.com")) ||
  629. name.equals(Name("a.t.example.com"))) {
  630. if (name.compare(wild_suffix).getRelation() ==
  631. NameComparisonResult::SUBDOMAIN) {
  632. domain = domains_.find(Name("*").concatenate(wild_suffix));
  633. // Matched the QNAME
  634. if (domain != domains_.end()) {
  635. RRsetStore::const_iterator found_rrset =
  636. domain->second.find(type);
  637. // Matched the QTYPE
  638. if(found_rrset != domain->second.end()) {
  639. return (createContext(options,SUCCESS, substituteWild(
  640. *found_rrset->second, name),
  641. RESULT_WILDCARD |
  642. (use_nsec3_ ?
  643. RESULT_NSEC3_SIGNED :
  644. RESULT_NSEC_SIGNED)));
  645. } else {
  646. // No matched QTYPE, this case is for NXRRSET with
  647. // WILDCARD
  648. if (use_nsec3_) {
  649. return (createContext(options, NXRRSET, RRsetPtr(),
  650. RESULT_WILDCARD |
  651. RESULT_NSEC3_SIGNED));
  652. }
  653. const Name new_name =
  654. Name("*").concatenate(wild_suffix);
  655. found_rrset = domain->second.find(RRType::NSEC());
  656. assert(found_rrset != domain->second.end());
  657. return (createContext(options, NXRRSET, substituteWild(
  658. *found_rrset->second,
  659. new_name),
  660. RESULT_WILDCARD |
  661. RESULT_NSEC_SIGNED));
  662. }
  663. } else {
  664. // This is empty non terminal name case on wildcard.
  665. const Name empty_name = Name("*").concatenate(wild_suffix);
  666. if (use_nsec3_) {
  667. return (createContext(options, NXRRSET, RRsetPtr(),
  668. RESULT_WILDCARD |
  669. RESULT_NSEC3_SIGNED));
  670. }
  671. for (Domains::reverse_iterator it = domains_.rbegin();
  672. it != domains_.rend();
  673. ++it) {
  674. RRsetStore::const_iterator nsec_it;
  675. if ((*it).first < empty_name &&
  676. (nsec_it = (*it).second.find(RRType::NSEC()))
  677. != (*it).second.end()) {
  678. return (createContext(options, NXRRSET,
  679. (*nsec_it).second,
  680. RESULT_WILDCARD |
  681. RESULT_NSEC_SIGNED));
  682. }
  683. }
  684. }
  685. return (createContext(options, NXRRSET, RRsetPtr(),
  686. RESULT_WILDCARD));
  687. }
  688. }
  689. const Name cnamewild_suffix("cnamewild.example.com");
  690. if (name.compare(cnamewild_suffix).getRelation() ==
  691. NameComparisonResult::SUBDOMAIN) {
  692. domain = domains_.find(Name("*").concatenate(cnamewild_suffix));
  693. assert(domain != domains_.end());
  694. RRsetStore::const_iterator found_rrset =
  695. domain->second.find(RRType::CNAME());
  696. assert(found_rrset != domain->second.end());
  697. return (createContext(options, CNAME,
  698. substituteWild(*found_rrset->second, name),
  699. RESULT_WILDCARD |
  700. (use_nsec3_ ? RESULT_NSEC3_SIGNED :
  701. RESULT_NSEC_SIGNED)));
  702. }
  703. }
  704. // This is an NXDOMAIN case.
  705. // If we need DNSSEC proof, find the "previous name" that has an NSEC RR
  706. // and return NXDOMAIN with the found NSEC. Otherwise, just return the
  707. // NXDOMAIN code and NULL. If DNSSEC proof is requested but no NSEC is
  708. // found, we return NULL, too. (For simplicity under the test conditions
  709. // we don't care about pathological cases such as the name is "smaller"
  710. // than the origin)
  711. if ((options & FIND_DNSSEC) != 0) {
  712. if (use_nsec3_) {
  713. return (createContext(options, NXDOMAIN, RRsetPtr(),
  714. RESULT_NSEC3_SIGNED));
  715. }
  716. // Emulate a broken DataSourceClient for some special names.
  717. if (nsec_context_ && nsec_name_ == name) {
  718. return (nsec_context_);
  719. }
  720. // Normal case
  721. // XXX: some older g++ complains about operator!= if we use
  722. // const_reverse_iterator
  723. for (Domains::reverse_iterator it = domains_.rbegin();
  724. it != domains_.rend();
  725. ++it) {
  726. RRsetStore::const_iterator nsec_it;
  727. if ((*it).first < name &&
  728. (nsec_it = (*it).second.find(RRType::NSEC()))
  729. != (*it).second.end()) {
  730. return (createContext(options, NXDOMAIN, (*nsec_it).second,
  731. RESULT_NSEC_SIGNED));
  732. }
  733. }
  734. }
  735. return (createContext(options,NXDOMAIN, RRsetPtr()));
  736. }
  737. enum DataSrcType {
  738. MOCK,
  739. INMEMORY,
  740. SQLITE3
  741. };
  742. boost::shared_ptr<ClientList>
  743. createDataSrcClientList(DataSrcType type, DataSourceClient& client) {
  744. boost::shared_ptr<ConfigurableClientList> list;
  745. switch (type) {
  746. case MOCK:
  747. return (boost::shared_ptr<ClientList>(new SingletonList(client)));
  748. case INMEMORY:
  749. list.reset(new ConfigurableClientList(RRClass::IN()));
  750. // Configure one normal zone and one "empty" zone.
  751. list->configure(isc::data::Element::fromJSON(
  752. "[{\"type\": \"MasterFiles\","
  753. " \"cache-enable\": true, "
  754. " \"params\": {\"example.com\": \"" +
  755. string(TEST_OWN_DATA_BUILDDIR "/example.zone\",") +
  756. + "\"" + EMPTY_ZONE_NAME + "\": \"" +
  757. string(TEST_OWN_DATA_BUILDDIR "/nosuchfile.zone") +
  758. "\"}}]"), true);
  759. return (list);
  760. case SQLITE3:
  761. // The copy should succeed; if it failed we should notice it in
  762. // test cases. However, we check the return value to avoid problems
  763. // in some glibcs where "system()" is annotated with the "warn unused
  764. // result" attribute.
  765. EXPECT_EQ(0, std::system(INSTALL_PROG " -c " TEST_OWN_DATA_BUILDDIR
  766. "/example-base.sqlite3 "
  767. TEST_OWN_DATA_BUILDDIR
  768. "/example-base.sqlite3.copied"));
  769. list.reset(new ConfigurableClientList(RRClass::IN()));
  770. list->configure(isc::data::Element::fromJSON(
  771. "[{\"type\": \"sqlite3\","
  772. " \"cache-enable\": false, "
  773. " \"cache-zones\": [], "
  774. " \"params\": {\"database_file\": \"" +
  775. string(TEST_OWN_DATA_BUILDDIR
  776. "/example-base.sqlite3.copied") +
  777. "\"}}]"), true);
  778. return (list);
  779. default:
  780. isc_throw(isc::Unexpected,
  781. "Unexpected data source type, should be a bug in test code");
  782. }
  783. }
  784. class MockClient : public DataSourceClient {
  785. public:
  786. virtual FindResult findZone(const isc::dns::Name& origin) const {
  787. // Identify the next (strictly) larger name than the given 'origin' in
  788. // the map. Its predecessor (if any) is the longest matching name
  789. // if it's either an exact match or a super domain; otherwise there's
  790. // no match in the map. See also datasrc/tests/mock_client.cc.
  791. // Eliminate the case of empty map to simply the rest of the code
  792. if (zone_finders_.empty()) {
  793. return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
  794. }
  795. std::map<Name, ZoneFinderPtr>::const_iterator it =
  796. zone_finders_.upper_bound(origin);
  797. if (it == zone_finders_.begin()) { // no predecessor
  798. return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
  799. }
  800. --it; // get the predecessor
  801. const result::ResultFlags flags =
  802. it->second ? result::FLAGS_DEFAULT : result::ZONE_EMPTY;
  803. const NameComparisonResult compar(it->first.compare(origin));
  804. switch (compar.getRelation()) {
  805. case NameComparisonResult::EQUAL:
  806. return (FindResult(result::SUCCESS, it->second, flags));
  807. case NameComparisonResult::SUPERDOMAIN:
  808. return (FindResult(result::PARTIALMATCH, it->second, flags));
  809. default:
  810. return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
  811. }
  812. }
  813. virtual ZoneUpdaterPtr getUpdater(const isc::dns::Name&, bool, bool) const
  814. {
  815. isc_throw(isc::NotImplemented,
  816. "Updater isn't supported in the MockClient");
  817. }
  818. virtual std::pair<ZoneJournalReader::Result, ZoneJournalReaderPtr>
  819. getJournalReader(const isc::dns::Name&, uint32_t, uint32_t) const {
  820. isc_throw(isc::NotImplemented,
  821. "Journaling isn't supported in the MockClient");
  822. }
  823. result::Result addZone(ZoneFinderPtr finder) {
  824. zone_finders_[finder->getOrigin()] = finder;
  825. return (result::SUCCESS);
  826. }
  827. // "configure" a zone with no data. This will cause the ZONE_EMPTY flag
  828. // on in finZone().
  829. result::Result addEmptyZone(const Name& zone_name) {
  830. zone_finders_[zone_name] = ZoneFinderPtr();
  831. return (result::SUCCESS);
  832. }
  833. private:
  834. // Note that because we no longer have the old RBTree, and the new
  835. // in-memory DomainTree is not useful as it returns const nodes, we
  836. // use a std::map instead.
  837. std::map<Name, ZoneFinderPtr> zone_finders_;
  838. };
  839. class QueryTest : public ::testing::TestWithParam<DataSrcType> {
  840. protected:
  841. QueryTest() :
  842. qname(Name("www.example.com")), qclass(RRClass::IN()),
  843. qtype(RRType::A()), response(Message::RENDER),
  844. qid(response.getQid()), query_code(Opcode::QUERY().getCode()),
  845. ns_addrs_and_sig_txt(string(ns_addrs_txt) +
  846. "glue.delegation.example.com. 3600 IN RRSIG " +
  847. getCommonRRSIGText("A") + "\n" +
  848. "glue.delegation.example.com. 3600 IN RRSIG " +
  849. getCommonRRSIGText("AAAA") + "\n" +
  850. "noglue.example.com. 3600 IN RRSIG " +
  851. getCommonRRSIGText("A")),
  852. base_zone_file(TEST_OWN_DATA_BUILDDIR "/example-base.zone"),
  853. nsec3_zone_file(TEST_OWN_DATA_BUILDDIR "/example-nsec3.zone"),
  854. common_zone_file(TEST_OWN_DATA_BUILDDIR "/example-common-inc.zone"),
  855. rrsets_added_(false)
  856. {
  857. // Set up the faked hash calculator.
  858. setNSEC3HashCreator(&nsec3hash_creator_);
  859. response.setRcode(Rcode::NOERROR());
  860. response.setOpcode(Opcode::QUERY());
  861. // create and add a matching zone. One is a "broken, empty" zone.
  862. mock_finder = new MockZoneFinder();
  863. mock_client.addZone(ZoneFinderPtr(mock_finder));
  864. mock_client.addEmptyZone(Name(EMPTY_ZONE_NAME));
  865. }
  866. virtual void SetUp() {
  867. // clear the commonly included zone file.
  868. ASSERT_EQ(0, std::system(INSTALL_PROG " -c " TEST_OWN_DATA_DIR
  869. "/example-common-inc-template.zone "
  870. TEST_OWN_DATA_BUILDDIR
  871. "/example-common-inc.zone"));
  872. // We create data source clients here, not in the constructor, so this
  873. // doesn't happen for derived test class. This also ensures the
  874. // data source clients are configured after setting NSEC3 hash in case
  875. // there's dependency.
  876. list_ = createDataSrcClientList(GetParam(), mock_client);
  877. }
  878. virtual void TearDown() {
  879. // make sure to clear the commonly included zone file to prevent
  880. // any remaining contents from affecting the next test.
  881. ASSERT_EQ(0, std::system(INSTALL_PROG " -c " TEST_OWN_DATA_DIR
  882. "/example-common-inc-template.zone "
  883. TEST_OWN_DATA_BUILDDIR
  884. "/example-common-inc.zone"));
  885. }
  886. virtual ~QueryTest() {
  887. // Make sure we reset the hash creator to the default
  888. setNSEC3HashCreator(NULL);
  889. }
  890. bool isEmptyZoneSupported() const {
  891. // Not all data sources support the concept of empty zones.
  892. // Specifically for this test, SQLite3-based data source doesn't.
  893. return (GetParam() != SQLITE3);
  894. }
  895. void enableNSEC3(const vector<string>& rrsets_to_add) {
  896. boost::shared_ptr<ConfigurableClientList> new_list;
  897. switch (GetParam()) {
  898. case MOCK:
  899. mock_finder->setNSEC3Flag(true);
  900. addRRsets(rrsets_to_add, *list_, "");
  901. break;
  902. case INMEMORY:
  903. addRRsets(rrsets_to_add, *list_, nsec3_zone_file);
  904. break;
  905. case SQLITE3:
  906. ASSERT_EQ(0, std::system(INSTALL_PROG " -c " TEST_OWN_DATA_BUILDDIR
  907. "/example-nsec3.sqlite3 "
  908. TEST_OWN_DATA_BUILDDIR
  909. "/example-nsec3.sqlite3.copied"));
  910. new_list.reset(new ConfigurableClientList(RRClass::IN()));
  911. new_list->configure(isc::data::Element::fromJSON(
  912. "[{\"type\": \"sqlite3\","
  913. " \"cache-enable\": false, "
  914. " \"cache-zones\": [], "
  915. " \"params\": {\"database_file\": \"" +
  916. string(TEST_OWN_DATA_BUILDDIR
  917. "/example-nsec3.sqlite3.copied") +
  918. "\"}}]"), true);
  919. addRRsets(rrsets_to_add, *new_list, "");
  920. list_ = new_list;
  921. break;
  922. }
  923. }
  924. // A helper to add some RRsets to the test zone in the middle of a test
  925. // case. The detailed behavior is quite different depending on the
  926. // data source type, and not all parameters are used in all cases.
  927. //
  928. // Note: due to limitation of its implementation, this method doesn't
  929. // work correctly for in-memory if called more than once. This condition
  930. // is explicitly checked so any accidental violation would be noted as a
  931. // test failure.
  932. void addRRsets(const vector<string>& rrsets_to_add, ClientList& list,
  933. const string& zone_file)
  934. {
  935. boost::shared_ptr<ConfigurableClientList> new_list;
  936. ofstream ofs;
  937. switch (GetParam()) {
  938. case MOCK:
  939. // directly add them to the mock data source; ignore the passed
  940. // list.
  941. for (vector<string>::const_iterator it = rrsets_to_add.begin();
  942. it != rrsets_to_add.end();
  943. ++it) {
  944. mock_finder->addRecord(*it);
  945. }
  946. break;
  947. case INMEMORY:
  948. ASSERT_FALSE(rrsets_added_);
  949. rrsets_added_ = true;
  950. // dump the RRsets to be added to the placeholder of commonly
  951. // included zone file (removing any existing contents) and do
  952. // full reconfiguration.
  953. ofs.open(common_zone_file.c_str(), ios_base::trunc);
  954. for (vector<string>::const_iterator it = rrsets_to_add.begin();
  955. it != rrsets_to_add.end();
  956. ++it) {
  957. ofs << *it << "\n";
  958. ofs << createRRSIG(textToRRset(*it))->toText() << "\n";
  959. }
  960. ofs.close();
  961. new_list.reset(new ConfigurableClientList(RRClass::IN()));
  962. new_list->configure(isc::data::Element::fromJSON(
  963. "[{\"type\": \"MasterFiles\","
  964. " \"cache-enable\": true, "
  965. " \"params\": {\"example.com\": \"" +
  966. zone_file + "\"}}]"), true);
  967. list_ = new_list;
  968. break;
  969. case SQLITE3:
  970. const Name origin("example.com");
  971. ZoneUpdaterPtr updater =
  972. list.find(origin, true, false).dsrc_client_->
  973. getUpdater(origin, false);
  974. for (vector<string>::const_iterator it = rrsets_to_add.begin();
  975. it != rrsets_to_add.end();
  976. ++it) {
  977. ConstRRsetPtr rrset = textToRRset(*it);
  978. updater->addRRset(*rrset);
  979. updater->addRRset(*createRRSIG(rrset));
  980. }
  981. updater->commit();
  982. break;
  983. }
  984. }
  985. private:
  986. // A helper for enableNSEC3, creating an RRSIG RRset for the corresponding
  987. // non-sig RRset, using the commonly used parameters.
  988. static ConstRRsetPtr createRRSIG(ConstRRsetPtr rrset) {
  989. RRsetPtr sig_rrset(new RRset(rrset->getName(), rrset->getClass(),
  990. RRType::RRSIG(), rrset->getTTL()));
  991. sig_rrset->addRdata(generic::RRSIG(
  992. getCommonRRSIGText(rrset->getType().
  993. toText())));
  994. return (sig_rrset);
  995. }
  996. protected:
  997. MockZoneFinder* mock_finder;
  998. MockClient mock_client;
  999. boost::shared_ptr<ClientList> list_;
  1000. const Name qname;
  1001. const RRClass qclass;
  1002. const RRType qtype;
  1003. Message response;
  1004. const qid_t qid;
  1005. const uint16_t query_code;
  1006. const string ns_addrs_and_sig_txt; // convenient shortcut
  1007. Query query;
  1008. TestNSEC3Hash nsec3_hash_;
  1009. vector<string> rrsets_to_add_;
  1010. const string base_zone_file;
  1011. private:
  1012. const string nsec3_zone_file;
  1013. const string common_zone_file;
  1014. const TestNSEC3HashCreator nsec3hash_creator_;
  1015. bool rrsets_added_;
  1016. };
  1017. // We test the in-memory and SQLite3 data source implementations. SQLite3
  1018. // will require a loadable module, which doesn't work with static link for
  1019. // all platforms.
  1020. INSTANTIATE_TEST_CASE_P(, QueryTest,
  1021. ::testing::Values(MOCK, INMEMORY
  1022. #ifndef USE_STATIC_LINK
  1023. , SQLITE3
  1024. #endif
  1025. ));
  1026. // This inherit the QueryTest cases except for the parameterized setup;
  1027. // it's intended to be used selected test cases that only work for mock
  1028. // data sources either because of some limitation or because of the type of
  1029. // tests (relying on a "broken" data source behavior that can't happen with
  1030. // production data source implementations).
  1031. class QueryTestForMockOnly : public QueryTest {
  1032. protected:
  1033. // Override SetUp() to avoid parameterized setup
  1034. virtual void SetUp() {
  1035. list_ = createDataSrcClientList(MOCK, mock_client);
  1036. }
  1037. };
  1038. // A wrapper to check resulting response message commonly used in
  1039. // tests below.
  1040. // check_origin needs to be specified only when the authority section has
  1041. // an SOA RR. The interface is not generic enough but should be okay
  1042. // for our test cases in practice.
  1043. void
  1044. responseCheck(Message& response, const isc::dns::Rcode& rcode,
  1045. unsigned int flags, const unsigned int ancount,
  1046. const unsigned int nscount, const unsigned int arcount,
  1047. const char* const expected_answer,
  1048. const char* const expected_authority,
  1049. const char* const expected_additional,
  1050. const Name& check_origin = Name::ROOT_NAME())
  1051. {
  1052. // In our test cases QID, Opcode, and QDCOUNT should be constant, so
  1053. // we don't bother the test cases specifying these values.
  1054. headerCheck(response, response.getQid(), rcode, Opcode::QUERY().getCode(),
  1055. flags, 0, ancount, nscount, arcount);
  1056. if (expected_answer != NULL) {
  1057. rrsetsCheck(expected_answer,
  1058. response.beginSection(Message::SECTION_ANSWER),
  1059. response.endSection(Message::SECTION_ANSWER),
  1060. check_origin);
  1061. }
  1062. if (expected_authority != NULL) {
  1063. rrsetsCheck(expected_authority,
  1064. response.beginSection(Message::SECTION_AUTHORITY),
  1065. response.endSection(Message::SECTION_AUTHORITY),
  1066. check_origin);
  1067. }
  1068. if (expected_additional != NULL) {
  1069. rrsetsCheck(expected_additional,
  1070. response.beginSection(Message::SECTION_ADDITIONAL),
  1071. response.endSection(Message::SECTION_ADDITIONAL));
  1072. }
  1073. }
  1074. TEST_P(QueryTest, noZone) {
  1075. // There's no zone in the memory datasource. So the response should have
  1076. // REFUSED.
  1077. MockClient empty_mock_client;
  1078. SingletonList empty_list(empty_mock_client);
  1079. EXPECT_NO_THROW(query.process(empty_list, qname, qtype, response));
  1080. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  1081. }
  1082. TEST_P(QueryTest, emptyZone) {
  1083. // Query for an "empty (broken)" zone. If the concept is supported by
  1084. // the underlying data source, the result should be SERVFAIL; otherwise
  1085. // it would be handled as a nonexistent zone, resulting in REFUSED.
  1086. const Rcode expected_rcode =
  1087. isEmptyZoneSupported() ? Rcode::SERVFAIL() : Rcode::REFUSED();
  1088. query.process(*list_, Name(EMPTY_ZONE_NAME), qtype, response);
  1089. responseCheck(response, expected_rcode, 0, 0, 0, 0, NULL, NULL, NULL);
  1090. // Same for the partial match case
  1091. response.clear(isc::dns::Message::RENDER);
  1092. response.setRcode(Rcode::NOERROR());
  1093. response.setOpcode(Opcode::QUERY());
  1094. query.process(*list_, Name(string("www.") + EMPTY_ZONE_NAME), qtype,
  1095. response);
  1096. responseCheck(response, expected_rcode, 0, 0, 0, 0, NULL, NULL, NULL);
  1097. }
  1098. TEST_P(QueryTest, exactMatch) {
  1099. EXPECT_NO_THROW(query.process(*list_, qname, qtype, response));
  1100. // find match rrset
  1101. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1102. www_a_txt, zone_ns_txt, ns_addrs_txt);
  1103. }
  1104. TEST_P(QueryTest, exactMatchMultipleQueries) {
  1105. EXPECT_NO_THROW(query.process(*list_, qname, qtype, response));
  1106. // find match rrset
  1107. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1108. www_a_txt, zone_ns_txt, ns_addrs_txt);
  1109. // clean up response for second query
  1110. response.clear(isc::dns::Message::RENDER);
  1111. response.setRcode(Rcode::NOERROR());
  1112. response.setOpcode(Opcode::QUERY());
  1113. EXPECT_NO_THROW(query.process(*list_, qname, qtype, response));
  1114. // find match rrset
  1115. SCOPED_TRACE("Second query");
  1116. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1117. www_a_txt, zone_ns_txt, ns_addrs_txt);
  1118. }
  1119. TEST_P(QueryTest, qtypeIsRRSIG) {
  1120. // Directly querying for RRSIGs should result in rcode=REFUSED.
  1121. EXPECT_NO_THROW(query.process(*list_, qname, RRType::RRSIG(), response));
  1122. responseCheck(response, Rcode::REFUSED(), AA_FLAG, 0, 0, 0,
  1123. "", "", "");
  1124. }
  1125. TEST_P(QueryTest, exactMatchIgnoreSIG) {
  1126. // Check that we do not include the RRSIG when not requested even when
  1127. // we receive it from the data source.
  1128. mock_finder->setIncludeRRSIGAnyway(true);
  1129. EXPECT_NO_THROW(query.process(*list_, qname, qtype, response));
  1130. // find match rrset
  1131. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1132. www_a_txt, zone_ns_txt, ns_addrs_txt);
  1133. }
  1134. TEST_P(QueryTest, dnssecPositive) {
  1135. // Just like exactMatch, but the signatures should be included as well
  1136. EXPECT_NO_THROW(query.process(*list_, qname, qtype, response, true));
  1137. // find match rrset
  1138. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 4, 6,
  1139. (www_a_txt + std::string("www.example.com. 3600 IN RRSIG "
  1140. "A 5 3 3600 20000101000000 "
  1141. "20000201000000 12345 example.com. "
  1142. "FAKEFAKEFAKE\n")).c_str(),
  1143. (zone_ns_txt + std::string("example.com. 3600 IN RRSIG NS 5 "
  1144. "3 3600 20000101000000 "
  1145. "20000201000000 12345 "
  1146. "example.com. FAKEFAKEFAKE\n")).
  1147. c_str(),
  1148. ns_addrs_and_sig_txt.c_str());
  1149. }
  1150. TEST_P(QueryTest, exactAddrMatch) {
  1151. // find match rrset, omit additional data which has already been provided
  1152. // in the answer section from the additional.
  1153. EXPECT_NO_THROW(query.process(*list_,
  1154. Name("noglue.example.com"),
  1155. qtype, response));
  1156. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 2,
  1157. "noglue.example.com. 3600 IN A 192.0.2.53\n", zone_ns_txt,
  1158. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  1159. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
  1160. }
  1161. TEST_P(QueryTest, apexNSMatch) {
  1162. // find match rrset, omit authority data which has already been provided
  1163. // in the answer section from the authority section.
  1164. EXPECT_NO_THROW(query.process(*list_, Name("example.com"),
  1165. RRType::NS(), response));
  1166. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 3, 0, 3,
  1167. zone_ns_txt, NULL, ns_addrs_txt);
  1168. }
  1169. // test type any query logic
  1170. TEST_P(QueryTest, exactAnyMatch) {
  1171. // find match rrset, omit additional data which has already been provided
  1172. // in the answer section from the additional.
  1173. EXPECT_NO_THROW(query.process(*list_, Name("noglue.example.com"),
  1174. RRType::ANY(), response));
  1175. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 3, 2,
  1176. (string("noglue.example.com. 3600 IN A 192.0.2.53\n") +
  1177. string(nsec_nxdomain_txt)).c_str(),
  1178. zone_ns_txt,
  1179. "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
  1180. "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
  1181. }
  1182. TEST_P(QueryTest, apexAnyMatch) {
  1183. // find match rrset, omit additional data which has already been provided
  1184. // in the answer section from the additional.
  1185. EXPECT_NO_THROW(query.process(*list_, Name("example.com"),
  1186. RRType::ANY(), response));
  1187. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 5, 0, 3,
  1188. (string(soa_txt) + string(zone_ns_txt) +
  1189. string(nsec_apex_txt)).c_str(),
  1190. NULL, ns_addrs_txt, mock_finder->getOrigin());
  1191. }
  1192. TEST_P(QueryTest, mxANYMatch) {
  1193. EXPECT_NO_THROW(query.process(*list_, Name("mx.example.com"),
  1194. RRType::ANY(), response));
  1195. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 4, 3, 4,
  1196. (string(mx_txt) + string(nsec_mx_txt)).c_str(), zone_ns_txt,
  1197. (string(ns_addrs_txt) + string(www_a_txt)).c_str());
  1198. }
  1199. TEST_P(QueryTest, glueANYMatch) {
  1200. EXPECT_NO_THROW(query.process(*list_, Name("delegation.example.com"),
  1201. RRType::ANY(), response));
  1202. responseCheck(response, Rcode::NOERROR(), 0, 0, 4, 3,
  1203. NULL, delegation_txt, ns_addrs_txt);
  1204. }
  1205. TEST_P(QueryTest, nodomainANY) {
  1206. EXPECT_NO_THROW(query.process(*list_, Name("nxdomain.example.com"),
  1207. RRType::ANY(), response));
  1208. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 1, 0,
  1209. NULL, soa_minttl_txt, NULL, mock_finder->getOrigin());
  1210. }
  1211. // This tests that when we need to look up Zone's apex NS records for
  1212. // authoritative answer, and there is no apex NS records. It should
  1213. // throw in that case.
  1214. //
  1215. // This only works with mock data source (for production datasrc the
  1216. // post-load would reject such a zone)
  1217. TEST_F(QueryTestForMockOnly, noApexNS) {
  1218. // Disable apex NS record
  1219. mock_finder->setApexNSFlag(false);
  1220. EXPECT_THROW(query.process(*list_, Name("noglue.example.com"), qtype,
  1221. response), Query::NoApexNS);
  1222. // We don't look into the response, as it threw
  1223. }
  1224. TEST_P(QueryTest, delegation) {
  1225. EXPECT_NO_THROW(query.process(*list_,
  1226. Name("delegation.example.com"),
  1227. qtype, response));
  1228. responseCheck(response, Rcode::NOERROR(), 0, 0, 4, 3,
  1229. NULL, delegation_txt, ns_addrs_txt);
  1230. }
  1231. TEST_P(QueryTest, delegationWithDNSSEC) {
  1232. // Similar to the previous one, but with requesting DNSSEC.
  1233. // In this case the parent zone would behave as unsigned, so the result
  1234. // should be just like non DNSSEC delegation.
  1235. query.process(*list_, Name("www.nosec-delegation.example.com"),
  1236. qtype, response, true);
  1237. responseCheck(response, Rcode::NOERROR(), 0, 0, 1, 0,
  1238. NULL, nosec_delegation_txt, NULL);
  1239. }
  1240. TEST_P(QueryTest, secureDelegation) {
  1241. EXPECT_NO_THROW(query.process(*list_,
  1242. Name("foo.signed-delegation.example.com"),
  1243. qtype, response, true));
  1244. // Should now contain RRSIG and DS record as well.
  1245. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  1246. NULL,
  1247. (string(signed_delegation_txt) +
  1248. string(signed_delegation_ds_txt) +
  1249. string("signed-delegation.example.com. 3600 IN RRSIG ") +
  1250. getCommonRRSIGText("DS")).c_str(),
  1251. NULL);
  1252. }
  1253. TEST_P(QueryTest, secureUnsignedDelegation) {
  1254. EXPECT_NO_THROW(query.process(*list_,
  1255. Name("foo.unsigned-delegation.example.com"),
  1256. qtype, response, true));
  1257. // Should now contain RRSIG and NSEC record as well.
  1258. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  1259. NULL,
  1260. (string(unsigned_delegation_txt) +
  1261. string(unsigned_delegation_nsec_txt) +
  1262. string("unsigned-delegation.example.com. 3600 IN RRSIG ") +
  1263. getCommonRRSIGText("NSEC")).c_str(),
  1264. NULL);
  1265. }
  1266. TEST_P(QueryTest, secureUnsignedDelegationWithNSEC3) {
  1267. // Similar to the previous case, but the zone is signed with NSEC3,
  1268. // and this delegation is NOT an optout.
  1269. rrsets_to_add_.push_back(unsigned_delegation_nsec3_txt);
  1270. enableNSEC3(rrsets_to_add_);
  1271. query.process(*list_,
  1272. Name("foo.unsigned-delegation.example.com"),
  1273. qtype, response, true);
  1274. // The response should contain the NS and matching NSEC3 with its RRSIG
  1275. const Name insecurechild_name("unsigned-delegation.example.com");
  1276. responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
  1277. NULL,
  1278. (string(unsigned_delegation_txt) +
  1279. string(unsigned_delegation_nsec3_txt) +
  1280. nsec3_hash_.calculate(insecurechild_name) +
  1281. ".example.com. 3600 IN RRSIG " +
  1282. getCommonRRSIGText("NSEC3")).c_str(),
  1283. NULL);
  1284. }
  1285. TEST_P(QueryTest, secureUnsignedDelegationWithNSEC3OptOut) {
  1286. // Similar to the previous case, but the delegation is an optout.
  1287. enableNSEC3(rrsets_to_add_);
  1288. query.process(*list_,
  1289. Name("foo.unsigned-delegation.example.com"),
  1290. qtype, response, true);
  1291. // The response should contain the NS and the closest provable encloser
  1292. // proof (and their RRSIGs). The closest encloser is the apex (origin),
  1293. // and with our faked hash the covering NSEC3 for the next closer
  1294. // (= child zone name) is that for www.example.com.
  1295. responseCheck(response, Rcode::NOERROR(), 0, 0, 5, 0,
  1296. NULL,
  1297. (string(unsigned_delegation_txt) +
  1298. string(nsec3_apex_txt) +
  1299. nsec3_hash_.calculate(mock_finder->getOrigin()) +
  1300. ".example.com. 3600 IN RRSIG " +
  1301. getCommonRRSIGText("NSEC3") + "\n" +
  1302. string(nsec3_www_txt) +
  1303. nsec3_hash_.calculate(Name("www.example.com")) +
  1304. ".example.com. 3600 IN RRSIG " +
  1305. getCommonRRSIGText("NSEC3")).c_str(),
  1306. NULL);
  1307. }
  1308. TEST_F(QueryTestForMockOnly, badSecureDelegation) {
  1309. // This is a broken data source scenario; works only with mock.
  1310. // Test whether exception is raised if DS query at delegation results in
  1311. // something different than SUCCESS or NXRRSET
  1312. EXPECT_THROW(query.process(*list_,
  1313. Name("bad-delegation.example.com"),
  1314. qtype, response, true), Query::BadDS);
  1315. // But only if DNSSEC is requested (it shouldn't even try to look for
  1316. // the DS otherwise)
  1317. EXPECT_NO_THROW(query.process(*list_,
  1318. Name("bad-delegation.example.com"),
  1319. qtype, response));
  1320. }
  1321. TEST_P(QueryTest, nxdomain) {
  1322. EXPECT_NO_THROW(query.process(*list_,
  1323. Name("nxdomain.example.com"), qtype,
  1324. response));
  1325. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 1, 0,
  1326. NULL, soa_minttl_txt, NULL, mock_finder->getOrigin());
  1327. }
  1328. TEST_P(QueryTest, nxdomainWithNSEC) {
  1329. // NXDOMAIN with DNSSEC proof. We should have SOA, NSEC that proves
  1330. // NXDOMAIN and NSEC that proves nonexistence of matching wildcard,
  1331. // as well as their RRSIGs.
  1332. EXPECT_NO_THROW(query.process(*list_,
  1333. Name("nxdomain.example.com"), qtype,
  1334. response, true));
  1335. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  1336. NULL, (string(soa_minttl_txt) +
  1337. string("example.com. 0 IN RRSIG ") +
  1338. getCommonRRSIGText("SOA") + "\n" +
  1339. string(nsec_nxdomain_txt) + "\n" +
  1340. string("noglue.example.com. 3600 IN RRSIG ") +
  1341. getCommonRRSIGText("NSEC") + "\n" +
  1342. string(nsec_apex_txt) + "\n" +
  1343. string("example.com. 3600 IN RRSIG ") +
  1344. getCommonRRSIGText("NSEC")).c_str(),
  1345. NULL, mock_finder->getOrigin());
  1346. }
  1347. TEST_P(QueryTest, nxdomainWithNSEC2) {
  1348. // See comments about no_txt. In this case the best possible wildcard
  1349. // is derived from the next domain of the NSEC that proves NXDOMAIN, and
  1350. // the NSEC to provide the non existence of wildcard is different from
  1351. // the first NSEC.
  1352. query.process(*list_, Name("!.no.example.com"), qtype, response,
  1353. true);
  1354. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  1355. NULL, (string(soa_minttl_txt) +
  1356. string("example.com. 0 IN RRSIG ") +
  1357. getCommonRRSIGText("SOA") + "\n" +
  1358. string(nsec_mx_txt) + "\n" +
  1359. string("mx.example.com. 3600 IN RRSIG ") +
  1360. getCommonRRSIGText("NSEC") + "\n" +
  1361. string(nsec_no_txt) + "\n" +
  1362. string("&.no.example.com. 3600 IN RRSIG ") +
  1363. getCommonRRSIGText("NSEC")).c_str(),
  1364. NULL, mock_finder->getOrigin());
  1365. }
  1366. TEST_P(QueryTest, nxdomainWithNSECDuplicate) {
  1367. // See comments about nz_txt. In this case we only need one NSEC,
  1368. // which proves both NXDOMAIN and the non existence of wildcard.
  1369. query.process(*list_, Name("nx.no.example.com"), qtype, response,
  1370. true);
  1371. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 4, 0,
  1372. NULL, (string(soa_minttl_txt) +
  1373. string("example.com. 0 IN RRSIG ") +
  1374. getCommonRRSIGText("SOA") + "\n" +
  1375. string(nsec_no_txt) + "\n" +
  1376. string("&.no.example.com. 3600 IN RRSIG ") +
  1377. getCommonRRSIGText("NSEC")).c_str(),
  1378. NULL, mock_finder->getOrigin());
  1379. }
  1380. TEST_F(QueryTestForMockOnly, nxdomainBadNSEC1) {
  1381. // This is a broken data source scenario; works only with mock.
  1382. // ZoneFinder::find() returns NXDOMAIN with non NSEC RR.
  1383. mock_finder->setNSECResult(Name("badnsec.example.com"),
  1384. ZoneFinder::NXDOMAIN,
  1385. mock_finder->dname_rrset_);
  1386. EXPECT_THROW(query.process(*list_, Name("badnsec.example.com"),
  1387. qtype, response, true),
  1388. std::bad_cast);
  1389. }
  1390. TEST_F(QueryTestForMockOnly, nxdomainBadNSEC2) {
  1391. // This is a broken data source scenario; works only with mock.
  1392. // ZoneFinder::find() returns NXDOMAIN with an empty NSEC RR.
  1393. mock_finder->setNSECResult(Name("emptynsec.example.com"),
  1394. ZoneFinder::NXDOMAIN,
  1395. mock_finder->empty_nsec_rrset_);
  1396. EXPECT_THROW(query.process(*list_, Name("emptynsec.example.com"),
  1397. qtype, response, true),
  1398. Query::BadNSEC);
  1399. }
  1400. TEST_F(QueryTestForMockOnly, nxdomainBadNSEC) {
  1401. // This is a broken data source scenario; works only with mock.
  1402. // "no-wildcard proof" returns SUCCESS. it should be NXDOMAIN.
  1403. mock_finder->setNSECResult(Name("*.example.com"),
  1404. ZoneFinder::SUCCESS,
  1405. mock_finder->dname_rrset_);
  1406. EXPECT_THROW(query.process(*list_, Name("nxdomain.example.com"),
  1407. qtype, response, true),
  1408. Query::BadNSEC);
  1409. }
  1410. TEST_F(QueryTestForMockOnly, nxdomainBadNSEC4) {
  1411. // This is a broken data source scenario; works only with mock.
  1412. // "no-wildcard proof" doesn't return RRset.
  1413. mock_finder->setNSECResult(Name("*.example.com"),
  1414. ZoneFinder::NXDOMAIN, ConstRRsetPtr());
  1415. EXPECT_THROW(query.process(*list_, Name("nxdomain.example.com"),
  1416. qtype, response, true),
  1417. Query::BadNSEC);
  1418. }
  1419. TEST_F(QueryTestForMockOnly, nxdomainBadNSEC5) {
  1420. // This is a broken data source scenario; works only with mock.
  1421. // "no-wildcard proof" returns non NSEC.
  1422. mock_finder->setNSECResult(Name("*.example.com"),
  1423. ZoneFinder::NXDOMAIN,
  1424. mock_finder->dname_rrset_);
  1425. // This is a bit odd, but we'll simply include the returned RRset.
  1426. query.process(*list_, Name("nxdomain.example.com"), qtype,
  1427. response, true);
  1428. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
  1429. NULL, (string(soa_minttl_txt) +
  1430. string("example.com. 0 IN RRSIG ") +
  1431. getCommonRRSIGText("SOA") + "\n" +
  1432. string(nsec_nxdomain_txt) + "\n" +
  1433. string("noglue.example.com. 3600 IN RRSIG ") +
  1434. getCommonRRSIGText("NSEC") + "\n" +
  1435. dname_txt + "\n" +
  1436. string("dname.example.com. 3600 IN RRSIG ") +
  1437. getCommonRRSIGText("DNAME")).c_str(),
  1438. NULL, mock_finder->getOrigin());
  1439. }
  1440. TEST_F(QueryTestForMockOnly, nxdomainBadNSEC6) {
  1441. // This is a broken data source scenario; works only with mock.
  1442. // "no-wildcard proof" returns empty NSEC.
  1443. mock_finder->setNSECResult(Name("*.example.com"),
  1444. ZoneFinder::NXDOMAIN,
  1445. mock_finder->empty_nsec_rrset_);
  1446. EXPECT_THROW(query.process(*list_, Name("nxdomain.example.com"),
  1447. qtype, response, true),
  1448. Query::BadNSEC);
  1449. }
  1450. TEST_P(QueryTest, nxrrset) {
  1451. EXPECT_NO_THROW(query.process(*list_, Name("www.example.com"),
  1452. RRType::TXT(), response));
  1453. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 1, 0,
  1454. NULL, soa_minttl_txt, NULL, mock_finder->getOrigin());
  1455. }
  1456. TEST_P(QueryTest, nxrrsetWithNSEC) {
  1457. // NXRRSET with DNSSEC proof. We should have SOA, NSEC that proves the
  1458. // NXRRSET and their RRSIGs.
  1459. query.process(*list_, Name("www.example.com"), RRType::TXT(),
  1460. response, true);
  1461. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1462. (string(soa_minttl_txt) +
  1463. string("example.com. 0 IN RRSIG ") +
  1464. getCommonRRSIGText("SOA") + "\n" +
  1465. string(nsec_www_txt) + "\n" +
  1466. string("www.example.com. 3600 IN RRSIG ") +
  1467. getCommonRRSIGText("NSEC")).c_str(),
  1468. NULL, mock_finder->getOrigin());
  1469. }
  1470. TEST_P(QueryTest, emptyNameWithNSEC) {
  1471. // Empty non terminal with DNSSEC proof. This is one of the cases of
  1472. // Section 3.1.3.2 of RFC4035.
  1473. // mx.example.com. NSEC &.no.example.com. proves no.example.com. is a
  1474. // non empty terminal node. Note that it also implicitly proves there
  1475. // should be no closer wildcard match (because the empty name is an
  1476. // exact match), so we only need one NSEC.
  1477. // From the point of the Query::process(), this is actually no different
  1478. // from the other NXRRSET case, but we check that explicitly just in case.
  1479. query.process(*list_, Name("no.example.com"), RRType::A(),
  1480. response, true);
  1481. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1482. (string(soa_minttl_txt) +
  1483. string("example.com. 0 IN RRSIG ") +
  1484. getCommonRRSIGText("SOA") + "\n" +
  1485. string(nsec_mx_txt) + "\n" +
  1486. string("mx.example.com. 3600 IN RRSIG ") +
  1487. getCommonRRSIGText("NSEC")).c_str(),
  1488. NULL, mock_finder->getOrigin());
  1489. }
  1490. TEST_P(QueryTest, nxrrsetWithoutNSEC) {
  1491. // NXRRSET with DNSSEC proof requested, but there's no NSEC at that node.
  1492. // This is an unexpected event (if the zone is supposed to be properly
  1493. // signed with NSECs), but we accept and ignore the oddity.
  1494. query.process(*list_, Name("nonsec.example.com"), RRType::TXT(),
  1495. response, true);
  1496. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 2, 0, NULL,
  1497. (string(soa_minttl_txt) +
  1498. string("example.com. 0 IN RRSIG ") +
  1499. getCommonRRSIGText("SOA") + "\n").c_str(),
  1500. NULL, mock_finder->getOrigin());
  1501. }
  1502. TEST_P(QueryTest, wildcardNSEC) {
  1503. // The qname matches *.wild.example.com. The response should contain
  1504. // an NSEC that proves the non existence of a closer name.
  1505. query.process(*list_, Name("www.wild.example.com"), RRType::A(),
  1506. response, true);
  1507. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 6, 6,
  1508. (string(wild_txt).replace(0, 1, "www") +
  1509. string("www.wild.example.com. 3600 IN RRSIG ") +
  1510. getCommonRRSIGText("A") + "\n").c_str(),
  1511. (zone_ns_txt + string("example.com. 3600 IN RRSIG NS 5 "
  1512. "3 3600 20000101000000 "
  1513. "20000201000000 12345 "
  1514. "example.com. FAKEFAKEFAKE\n") +
  1515. string(nsec_wild_txt) +
  1516. string("*.wild.example.com. 3600 IN RRSIG ") +
  1517. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1518. NULL, // we are not interested in additionals in this test
  1519. mock_finder->getOrigin());
  1520. }
  1521. TEST_P(QueryTest, CNAMEwildNSEC) {
  1522. // Similar to the previous case, but the matching wildcard record is
  1523. // CNAME.
  1524. query.process(*list_, Name("www.cnamewild.example.com"),
  1525. RRType::A(), response, true);
  1526. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
  1527. (string(cnamewild_txt).replace(0, 1, "www") +
  1528. string("www.cnamewild.example.com. 3600 IN RRSIG ") +
  1529. getCommonRRSIGText("CNAME") + "\n").c_str(),
  1530. (string(nsec_cnamewild_txt) +
  1531. string("*.cnamewild.example.com. 3600 IN RRSIG ") +
  1532. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1533. NULL, // we are not interested in additionals in this test
  1534. mock_finder->getOrigin());
  1535. }
  1536. TEST_P(QueryTest, wildcardNSEC3) {
  1537. // Similar to wildcardNSEC, but the zone is signed with NSEC3.
  1538. // The next closer is y.wild.example.com, the covering NSEC3 for it
  1539. // is (in our setup) the NSEC3 for the apex.
  1540. //
  1541. // Adding NSEC3 for wild.example.com, which will be used in the middle
  1542. // of identifying the next closer name.
  1543. rrsets_to_add_.push_back(nsec3_atwild_txt);
  1544. enableNSEC3(rrsets_to_add_);
  1545. query.process(*list_, Name("x.y.wild.example.com"), RRType::A(),
  1546. response, true);
  1547. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 6, 6,
  1548. (string(wild_txt).replace(0, 1, "x.y") +
  1549. string("x.y.wild.example.com. 3600 IN RRSIG ") +
  1550. getCommonRRSIGText("A") + "\n").c_str(),
  1551. // 3 NSes and their RRSIG
  1552. (zone_ns_txt + string("example.com. 3600 IN RRSIG ") +
  1553. getCommonRRSIGText("NS") + "\n" +
  1554. // NSEC3 for the wildcard proof and its RRSIG
  1555. string(nsec3_apex_txt) +
  1556. nsec3_hash_.calculate(Name("example.com.")) +
  1557. string(".example.com. 3600 IN RRSIG ") +
  1558. getCommonRRSIGText("NSEC3")).c_str(),
  1559. NULL, // we are not interested in additionals in this test
  1560. mock_finder->getOrigin());
  1561. }
  1562. TEST_P(QueryTest, CNAMEwildNSEC3) {
  1563. // Similar to CNAMEwildNSEC, but with NSEC3.
  1564. // The next closer is qname itself, the covering NSEC3 for it
  1565. // is (in our setup) the NSEC3 for the www.example.com.
  1566. rrsets_to_add_.push_back(nsec3_atcnamewild_txt);
  1567. enableNSEC3(rrsets_to_add_);
  1568. query.process(*list_, Name("www.cnamewild.example.com"),
  1569. RRType::A(), response, true);
  1570. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
  1571. (string(cnamewild_txt).replace(0, 1, "www") +
  1572. string("www.cnamewild.example.com. 3600 IN RRSIG ") +
  1573. getCommonRRSIGText("CNAME") + "\n").c_str(),
  1574. (string(nsec3_www_txt) +
  1575. nsec3_hash_.calculate(Name("www.example.com.")) +
  1576. string(".example.com. 3600 IN RRSIG ") +
  1577. getCommonRRSIGText("NSEC3")).c_str(),
  1578. NULL, // we are not interested in additionals in this test
  1579. mock_finder->getOrigin());
  1580. }
  1581. TEST_F(QueryTestForMockOnly, badWildcardNSEC3) {
  1582. // This is a broken data source scenario; works only with mock.
  1583. // Similar to wildcardNSEC3, but emulating run time collision by
  1584. // returning NULL in the next closer proof for the closest encloser
  1585. // proof.
  1586. mock_finder->setNSEC3Flag(true);
  1587. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  1588. ConstRRsetPtr());
  1589. mock_finder->setNSEC3Result(&nsec3);
  1590. EXPECT_THROW(query.process(*list_, Name("www.wild.example.com"),
  1591. RRType::A(), response, true),
  1592. Query::BadNSEC3);
  1593. }
  1594. TEST_F(QueryTestForMockOnly, badWildcardProof1) {
  1595. // This is a broken data source scenario; works only with mock.
  1596. // Unexpected case in wildcard proof: ZoneFinder::find() returns SUCCESS
  1597. // when NXDOMAIN is expected.
  1598. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1599. ZoneFinder::SUCCESS,
  1600. mock_finder->dname_rrset_);
  1601. EXPECT_THROW(query.process(*list_, Name("www.wild.example.com"),
  1602. RRType::A(), response, true),
  1603. Query::BadNSEC);
  1604. }
  1605. TEST_F(QueryTestForMockOnly, badWildcardProof2) {
  1606. // This is a broken data source scenario; works only with mock.
  1607. // "wildcard proof" doesn't return RRset.
  1608. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1609. ZoneFinder::NXDOMAIN, ConstRRsetPtr());
  1610. EXPECT_THROW(query.process(*list_, Name("www.wild.example.com"),
  1611. RRType::A(), response, true),
  1612. Query::BadNSEC);
  1613. }
  1614. TEST_F(QueryTestForMockOnly, badWildcardProof3) {
  1615. // This is a broken data source scenario; works only with mock.
  1616. // "wildcard proof" returns empty NSEC.
  1617. mock_finder->setNSECResult(Name("www.wild.example.com"),
  1618. ZoneFinder::NXDOMAIN,
  1619. mock_finder->empty_nsec_rrset_);
  1620. EXPECT_THROW(query.process(*list_, Name("www.wild.example.com"),
  1621. RRType::A(), response, true),
  1622. Query::BadNSEC);
  1623. }
  1624. TEST_P(QueryTest, wildcardNxrrsetWithDuplicateNSEC) {
  1625. // NXRRSET on WILDCARD with DNSSEC proof. We should have SOA, NSEC that
  1626. // proves the NXRRSET and their RRSIGs. In this case we only need one NSEC,
  1627. // which proves both NXDOMAIN and the non existence RRSETs of wildcard.
  1628. query.process(*list_, Name("www.wild.example.com"), RRType::TXT(),
  1629. response, true);
  1630. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  1631. (string(soa_minttl_txt) +
  1632. string("example.com. 0 IN RRSIG ") +
  1633. getCommonRRSIGText("SOA") + "\n" +
  1634. string(nsec_wild_txt) +
  1635. string("*.wild.example.com. 3600 IN RRSIG ") +
  1636. getCommonRRSIGText("NSEC")+"\n").c_str(),
  1637. NULL, mock_finder->getOrigin());
  1638. }
  1639. TEST_P(QueryTest, wildcardNxrrsetWithNSEC) {
  1640. // WILDCARD + NXRRSET with DNSSEC proof. We should have SOA, NSEC that
  1641. // proves the NXRRSET and their RRSIGs. In this case we need two NSEC RRs,
  1642. // one proves NXDOMAIN and the other proves non existence RRSETs of
  1643. // wildcard.
  1644. query.process(*list_, Name("www1.uwild.example.com"),
  1645. RRType::TXT(), response, true);
  1646. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  1647. (string(soa_minttl_txt) +
  1648. string("example.com. 0 IN RRSIG ") +
  1649. getCommonRRSIGText("SOA") + "\n" +
  1650. string(nsec_wild_txt_nxrrset) +
  1651. string("*.uwild.example.com. 3600 IN RRSIG ") +
  1652. getCommonRRSIGText("NSEC")+"\n" +
  1653. string(nsec_wild_txt_next) +
  1654. string("www.uwild.example.com. 3600 IN RRSIG ") +
  1655. getCommonRRSIGText("NSEC") + "\n").c_str(),
  1656. NULL, mock_finder->getOrigin());
  1657. }
  1658. TEST_P(QueryTest, wildcardNxrrsetWithNSEC3) {
  1659. // Similar to the previous case, but providing NSEC3 proofs according to
  1660. // RFC5155 Section 7.2.5.
  1661. rrsets_to_add_.push_back(nsec3_wild_txt);
  1662. rrsets_to_add_.push_back(nsec3_uwild_txt);
  1663. enableNSEC3(rrsets_to_add_);
  1664. query.process(*list_, Name("www1.uwild.example.com"),
  1665. RRType::TXT(), response, true);
  1666. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 8, 0, NULL,
  1667. // SOA + its RRSIG
  1668. (string(soa_minttl_txt) +
  1669. string("example.com. 0 IN RRSIG ") +
  1670. getCommonRRSIGText("SOA") + "\n" +
  1671. // NSEC3 for the closest encloser + its RRSIG
  1672. string(nsec3_uwild_txt) +
  1673. nsec3_hash_.calculate(Name("uwild.example.com.")) +
  1674. ".example.com. 3600 IN RRSIG " +
  1675. getCommonRRSIGText("NSEC3") + "\n" +
  1676. // NSEC3 for the next closer + its RRSIG
  1677. string(nsec3_www_txt) +
  1678. nsec3_hash_.calculate(Name("www.example.com.")) +
  1679. ".example.com. 3600 IN RRSIG " +
  1680. getCommonRRSIGText("NSEC3") + "\n" +
  1681. // NSEC3 for the wildcard + its RRSIG
  1682. string(nsec3_wild_txt) +
  1683. nsec3_hash_.calculate(Name("*.uwild.example.com.")) +
  1684. ".example.com. 3600 IN RRSIG " +
  1685. getCommonRRSIGText("NSEC3")).c_str(),
  1686. NULL, mock_finder->getOrigin());
  1687. }
  1688. TEST_F(QueryTestForMockOnly, wildcardNxrrsetWithNSEC3Collision) {
  1689. // This is a broken data source scenario; works only with mock.
  1690. // Similar to the previous case, but emulating run time collision by
  1691. // returning NULL in the next closer proof for the closest encloser
  1692. // proof.
  1693. mock_finder->setNSEC3Flag(true);
  1694. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  1695. ConstRRsetPtr());
  1696. mock_finder->setNSEC3Result(&nsec3);
  1697. EXPECT_THROW(query.process(*list_, Name("www1.uwild.example.com"),
  1698. RRType::TXT(), response, true),
  1699. Query::BadNSEC3);
  1700. }
  1701. TEST_F(QueryTestForMockOnly, wildcardNxrrsetWithNSEC3Broken) {
  1702. // This is a broken data source scenario; works only with mock.
  1703. // Similar to wildcardNxrrsetWithNSEC3, but no matching NSEC3 for the
  1704. // wildcard name will be returned. This shouldn't happen in a reasonably
  1705. // NSEC3-signed zone, and should result in an exception.
  1706. mock_finder->setNSEC3Flag(true);
  1707. const Name wname("*.uwild.example.com.");
  1708. ZoneFinder::FindNSEC3Result nsec3(false, 0, textToRRset(nsec3_apex_txt),
  1709. ConstRRsetPtr());
  1710. mock_finder->setNSEC3Result(&nsec3, &wname);
  1711. mock_finder->addRecord(nsec3_wild_txt);
  1712. mock_finder->addRecord(nsec3_uwild_txt);
  1713. EXPECT_THROW(query.process(*list_, Name("www1.uwild.example.com"),
  1714. RRType::TXT(), response, true),
  1715. Query::BadNSEC3);
  1716. }
  1717. TEST_P(QueryTest, wildcardEmptyWithNSEC) {
  1718. // Empty WILDCARD with DNSSEC proof. We should have SOA, NSEC that proves
  1719. // the NXDOMAIN and their RRSIGs. In this case we need two NSEC RRs,
  1720. // one proves NXDOMAIN and the other proves non existence wildcard.
  1721. query.process(*list_, Name("a.t.example.com"), RRType::A(),
  1722. response, true);
  1723. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  1724. (string(soa_minttl_txt) +
  1725. string("example.com. 0 IN RRSIG ") +
  1726. getCommonRRSIGText("SOA") + "\n" +
  1727. string(nsec_empty_prev_txt) +
  1728. string("t.example.com. 3600 IN RRSIG ") +
  1729. getCommonRRSIGText("NSEC")+"\n" +
  1730. string(nsec_empty_txt) +
  1731. string("b.*.t.example.com. 3600 IN RRSIG ") +
  1732. getCommonRRSIGText("NSEC")+"\n").c_str(),
  1733. NULL, mock_finder->getOrigin());
  1734. }
  1735. /*
  1736. * This tests that when there's no SOA and we need a negative answer. It should
  1737. * throw in that case.
  1738. */
  1739. TEST_F(QueryTestForMockOnly, noSOA) {
  1740. // This is a broken data source scenario; works only with mock.
  1741. // disable zone's SOA RR.
  1742. mock_finder->setSOAFlag(false);
  1743. // The NX Domain
  1744. EXPECT_THROW(query.process(*list_, Name("nxdomain.example.com"),
  1745. qtype, response), Query::NoSOA);
  1746. // Of course, we don't look into the response, as it throwed
  1747. // NXRRSET
  1748. EXPECT_THROW(query.process(*list_, Name("nxrrset.example.com"),
  1749. qtype, response), Query::NoSOA);
  1750. }
  1751. TEST_P(QueryTest, noMatchZone) {
  1752. // there's a zone in the memory datasource but it doesn't match the qname.
  1753. // should result in REFUSED.
  1754. query.process(*list_, Name("example.org"), qtype, response);
  1755. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  1756. }
  1757. /*
  1758. * Test MX additional processing.
  1759. *
  1760. * The MX RRset has two RRs, one pointing to a known domain with
  1761. * A record, other to unknown out of zone one.
  1762. */
  1763. TEST_P(QueryTest, MX) {
  1764. query.process(*list_, Name("mx.example.com"), RRType::MX(),
  1765. response);
  1766. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 3, 3, 4,
  1767. mx_txt, NULL,
  1768. (string(ns_addrs_txt) + string(www_a_txt)).c_str());
  1769. }
  1770. /*
  1771. * Test when we ask for MX whose exchange is an alias (CNAME in this case).
  1772. *
  1773. * This should not trigger the additional processing for the exchange.
  1774. */
  1775. TEST_P(QueryTest, MXAlias) {
  1776. query.process(*list_, Name("cnamemx.example.com"), RRType::MX(),
  1777. response);
  1778. // there shouldn't be no additional RRs for the exchanges (we have 3
  1779. // RRs for the NS). The normal MX case is tested separately so we don't
  1780. // bother to examine the answer (and authority) sections.
  1781. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1782. NULL, NULL, ns_addrs_txt);
  1783. }
  1784. /*
  1785. * Tests encountering a cname.
  1786. *
  1787. * There are tests leading to successful answers, NXRRSET, NXDOMAIN and
  1788. * out of the zone.
  1789. *
  1790. * TODO: We currently don't do chaining, so only the CNAME itself should be
  1791. * returned.
  1792. */
  1793. TEST_P(QueryTest, CNAME) {
  1794. query.process(*list_, Name("cname.example.com"), RRType::A(),
  1795. response);
  1796. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1797. cname_txt, NULL, NULL);
  1798. }
  1799. TEST_P(QueryTest, explicitCNAME) {
  1800. // same owner name as the CNAME test but explicitly query for CNAME RR.
  1801. // expect the same response as we don't provide a full chain yet.
  1802. query.process(*list_, Name("cname.example.com"), RRType::CNAME(),
  1803. response);
  1804. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1805. cname_txt, zone_ns_txt, ns_addrs_txt);
  1806. }
  1807. TEST_P(QueryTest, CNAME_NX_RRSET) {
  1808. // Leads to www.example.com, it doesn't have TXT
  1809. // note: with chaining, what should be expected is not trivial:
  1810. // BIND 9 returns the CNAME in answer and SOA in authority, no additional.
  1811. // NSD returns the CNAME, NS in authority, A/AAAA for NS in additional.
  1812. query.process(*list_, Name("cname.example.com"), RRType::TXT(),
  1813. response);
  1814. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1815. cname_txt, NULL, NULL);
  1816. }
  1817. TEST_P(QueryTest, explicitCNAME_NX_RRSET) {
  1818. // same owner name as the NXRRSET test but explicitly query for CNAME RR.
  1819. query.process(*list_, Name("cname.example.com"), RRType::CNAME(),
  1820. response);
  1821. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1822. cname_txt, zone_ns_txt, ns_addrs_txt);
  1823. }
  1824. TEST_P(QueryTest, CNAME_NX_DOMAIN) {
  1825. // Leads to nxdomain.example.com
  1826. // note: with chaining, what should be expected is not trivial:
  1827. // BIND 9 returns the CNAME in answer and SOA in authority, no additional,
  1828. // RCODE being NXDOMAIN.
  1829. // NSD returns the CNAME, NS in authority, A/AAAA for NS in additional,
  1830. // RCODE being NOERROR.
  1831. query.process(*list_, Name("cnamenxdom.example.com"), RRType::A(),
  1832. response);
  1833. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1834. cname_nxdom_txt, NULL, NULL);
  1835. }
  1836. TEST_P(QueryTest, explicitCNAME_NX_DOMAIN) {
  1837. // same owner name as the NXDOMAIN test but explicitly query for CNAME RR.
  1838. query.process(*list_, Name("cnamenxdom.example.com"),
  1839. RRType::CNAME(), response);
  1840. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1841. cname_nxdom_txt, zone_ns_txt, ns_addrs_txt);
  1842. }
  1843. TEST_P(QueryTest, CNAME_OUT) {
  1844. /*
  1845. * This leads out of zone. This should have only the CNAME even
  1846. * when we do chaining.
  1847. *
  1848. * TODO: We should be able to have two zones in the mock data source.
  1849. * Then the same test should be done with .org included there and
  1850. * see what it does (depends on what we want to do)
  1851. */
  1852. query.process(*list_, Name("cnameout.example.com"), RRType::A(),
  1853. response);
  1854. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 0, 0,
  1855. cname_out_txt, NULL, NULL);
  1856. }
  1857. TEST_P(QueryTest, explicitCNAME_OUT) {
  1858. // same owner name as the OUT test but explicitly query for CNAME RR.
  1859. query.process(*list_, Name("cnameout.example.com"), RRType::CNAME(),
  1860. response);
  1861. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1862. cname_out_txt, zone_ns_txt, ns_addrs_txt);
  1863. }
  1864. /*
  1865. * Test a query under a domain with DNAME. We should get a synthetized CNAME
  1866. * as well as the DNAME.
  1867. *
  1868. * TODO: Once we have CNAME chaining, check it works with synthetized CNAMEs
  1869. * as well. This includes tests pointing inside the zone, outside the zone,
  1870. * pointing to NXRRSET and NXDOMAIN cases (similarly as with CNAME).
  1871. */
  1872. TEST_P(QueryTest, DNAME) {
  1873. query.process(*list_, Name("www.dname.example.com"), RRType::A(),
  1874. response);
  1875. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1876. (string(dname_txt) + synthetized_cname_txt).c_str(),
  1877. NULL, NULL);
  1878. }
  1879. /*
  1880. * Ask an ANY query below a DNAME. Should return the DNAME and synthetized
  1881. * CNAME.
  1882. *
  1883. * ANY is handled specially sometimes. We check it is not the case with
  1884. * DNAME.
  1885. */
  1886. TEST_P(QueryTest, DNAME_ANY) {
  1887. query.process(*list_, Name("www.dname.example.com"), RRType::ANY(),
  1888. response);
  1889. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1890. (string(dname_txt) + synthetized_cname_txt).c_str(), NULL, NULL);
  1891. }
  1892. // Test when we ask for DNAME explicitly, it does no synthetizing.
  1893. TEST_P(QueryTest, explicitDNAME) {
  1894. query.process(*list_, Name("dname.example.com"), RRType::DNAME(),
  1895. response);
  1896. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1897. dname_txt, zone_ns_txt, ns_addrs_txt);
  1898. }
  1899. /*
  1900. * Request a RRset at the domain with DNAME. It should not synthetize
  1901. * the CNAME, it should return the RRset.
  1902. */
  1903. TEST_P(QueryTest, DNAME_A) {
  1904. query.process(*list_, Name("dname.example.com"), RRType::A(),
  1905. response);
  1906. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
  1907. dname_a_txt, zone_ns_txt, ns_addrs_txt);
  1908. }
  1909. /*
  1910. * Request a RRset at the domain with DNAME that is not there (NXRRSET).
  1911. * It should not synthetize the CNAME.
  1912. */
  1913. TEST_P(QueryTest, DNAME_NX_RRSET) {
  1914. EXPECT_NO_THROW(query.process(*list_, Name("dname.example.com"),
  1915. RRType::TXT(), response));
  1916. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 1, 0,
  1917. NULL, soa_minttl_txt, NULL, mock_finder->getOrigin());
  1918. }
  1919. /*
  1920. * Constructing the CNAME will result in a name that is too long. This,
  1921. * however, should not throw (and crash the server), but respond with
  1922. * YXDOMAIN.
  1923. */
  1924. TEST_P(QueryTest, LongDNAME) {
  1925. // A name that is as long as it can be
  1926. Name longname(
  1927. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1928. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1929. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1930. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1931. "dname.example.com.");
  1932. EXPECT_NO_THROW(query.process(*list_, longname, RRType::A(),
  1933. response));
  1934. responseCheck(response, Rcode::YXDOMAIN(), AA_FLAG, 1, 0, 0,
  1935. dname_txt, NULL, NULL);
  1936. }
  1937. /*
  1938. * Constructing the CNAME will result in a name of maximal length.
  1939. * This tests that we don't reject valid one by some kind of off by
  1940. * one mistake.
  1941. */
  1942. TEST_P(QueryTest, MaxLenDNAME) {
  1943. Name longname(
  1944. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1945. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1946. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1947. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
  1948. "dname.example.com.");
  1949. EXPECT_NO_THROW(query.process(*list_, longname, RRType::A(),
  1950. response));
  1951. // Check the answer is OK
  1952. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 0, 0,
  1953. NULL, NULL, NULL);
  1954. // Check that the CNAME has the maximal length.
  1955. bool ok(false);
  1956. for (RRsetIterator i(response.beginSection(Message::SECTION_ANSWER));
  1957. i != response.endSection(Message::SECTION_ANSWER); ++ i) {
  1958. if ((*i)->getType() == RRType::CNAME()) {
  1959. ok = true;
  1960. RdataIteratorPtr ci((*i)->getRdataIterator());
  1961. ASSERT_FALSE(ci->isLast()) << "The CNAME is empty";
  1962. /*
  1963. * Does anybody have a clue why, if the Name::MAX_WIRE is put
  1964. * directly inside ASSERT_EQ, it fails to link and complains
  1965. * it is unresolved external?
  1966. */
  1967. const size_t max_len(Name::MAX_WIRE);
  1968. ASSERT_EQ(max_len, dynamic_cast<const rdata::generic::CNAME&>(
  1969. ci->getCurrent()).getCname().getLength());
  1970. }
  1971. }
  1972. EXPECT_TRUE(ok) << "The synthetized CNAME not found";
  1973. }
  1974. // Test for this test module itself
  1975. void
  1976. nsec3Check(bool expected_matched, uint8_t expected_labels,
  1977. const string& expected_rrsets_txt,
  1978. const ZoneFinder::FindNSEC3Result& result)
  1979. {
  1980. vector<ConstRRsetPtr> actual_rrsets;
  1981. EXPECT_EQ(expected_matched, result.matched);
  1982. // Convert to int so the error messages would be more readable:
  1983. EXPECT_EQ(static_cast<int>(expected_labels),
  1984. static_cast<int>(result.closest_labels));
  1985. if (result.closest_proof) {
  1986. actual_rrsets.push_back(result.closest_proof);
  1987. }
  1988. if (result.next_proof) {
  1989. actual_rrsets.push_back(result.next_proof);
  1990. }
  1991. rrsetsCheck(expected_rrsets_txt, actual_rrsets.begin(),
  1992. actual_rrsets.end());
  1993. }
  1994. TEST_F(QueryTestForMockOnly, findNSEC3) {
  1995. // This test is intended to test the mock data source behavior; no need
  1996. // to do it for others.
  1997. // In all test cases in the recursive mode, the closest encloser is the
  1998. // apex, and result's closest_labels should be the number of apex labels.
  1999. // (In non recursive mode closest_labels should be the # labels of the
  2000. // query name)
  2001. const uint8_t expected_closest_labels =
  2002. Name("example.com").getLabelCount();
  2003. // Apex name. It should have a matching NSEC3
  2004. {
  2005. SCOPED_TRACE("apex, non recursive");
  2006. nsec3Check(true, expected_closest_labels,
  2007. string(nsec3_apex_txt) + "\n" + nsec3_apex_rrsig_txt,
  2008. mock_finder->findNSEC3(Name("example.com"), false));
  2009. }
  2010. // Recursive mode doesn't change the result in this case.
  2011. {
  2012. SCOPED_TRACE("apex, recursive");
  2013. nsec3Check(true, expected_closest_labels,
  2014. string(nsec3_apex_txt) + "\n" + nsec3_apex_rrsig_txt,
  2015. mock_finder->findNSEC3(Name("example.com"), true));
  2016. }
  2017. // Non existent name. Disabling recursion, a covering NSEC3 should be
  2018. // returned.
  2019. {
  2020. SCOPED_TRACE("nxdomain, non recursive");
  2021. nsec3Check(false, 4,
  2022. string(nsec3_www_txt) + "\n" + nsec3_www_rrsig_txt,
  2023. mock_finder->findNSEC3(Name("nxdomain.example.com"),
  2024. false));
  2025. }
  2026. // Non existent name. The closest provable encloser is the apex,
  2027. // and next closer is the query name.
  2028. {
  2029. SCOPED_TRACE("nxdomain, recursive");
  2030. nsec3Check(true, expected_closest_labels,
  2031. string(nsec3_apex_txt) + "\n" + nsec3_apex_rrsig_txt + "\n" +
  2032. nsec3_www_txt + "\n" + nsec3_www_rrsig_txt,
  2033. mock_finder->findNSEC3(Name("nxdomain.example.com"), true));
  2034. }
  2035. // Similar to the previous case, but next closer name is different
  2036. // (is the parent) of the non existent name.
  2037. {
  2038. SCOPED_TRACE("nxdomain, next closer != qname");
  2039. nsec3Check(true, expected_closest_labels,
  2040. string(nsec3_apex_txt) + "\n" +
  2041. nsec3_apex_rrsig_txt + "\n" +
  2042. nsec3_www_txt + "\n" + nsec3_www_rrsig_txt,
  2043. mock_finder->findNSEC3(Name("nx.domain.example.com"),
  2044. true));
  2045. }
  2046. // In the rest of test we check hash comparison for wrap around cases.
  2047. {
  2048. SCOPED_TRACE("largest");
  2049. nsec3Check(false, 4,
  2050. string(nsec3_apex_txt) + "\n" + nsec3_apex_rrsig_txt,
  2051. mock_finder->findNSEC3(Name("nxdomain2.example.com"),
  2052. false));
  2053. }
  2054. {
  2055. SCOPED_TRACE("smallest");
  2056. nsec3Check(false, 4,
  2057. string(nsec3_www_txt) + "\n" + nsec3_www_rrsig_txt,
  2058. mock_finder->findNSEC3(Name("nxdomain3.example.com"),
  2059. false));
  2060. }
  2061. }
  2062. // This tests that the DS is returned above the delegation point as
  2063. // an authoritative answer, not a delegation. This is as described in
  2064. // RFC 4035, section 3.1.4.1.
  2065. // This mock finder is used for some DS-query tests to support the cases
  2066. // where the query is expected to be handled in a different zone than our
  2067. // main test zone, example.com. Only limited methods are expected to called
  2068. // (and for limited purposes) on this class object in these tests, which
  2069. // are overridden below.
  2070. class AlternateZoneFinder : public MockZoneFinder {
  2071. public:
  2072. // This zone is expected not to have a DS by default and return NXRRSET
  2073. // for a DS query. If have_ds is set to true on construction, it will
  2074. // return a faked DS answer.
  2075. AlternateZoneFinder(const Name& origin, bool have_ds = false) :
  2076. MockZoneFinder(), origin_(origin), have_ds_(have_ds)
  2077. {}
  2078. virtual isc::dns::Name getOrigin() const { return (origin_); }
  2079. virtual ZoneFinderContextPtr find(const isc::dns::Name&,
  2080. const isc::dns::RRType& type,
  2081. const FindOptions options)
  2082. {
  2083. if (type == RRType::SOA()) {
  2084. RRsetPtr soa = textToRRset(origin_.toText() + " 3600 IN SOA . . "
  2085. "0 0 0 0 0\n", origin_);
  2086. soa->addRRsig(RdataPtr(new generic::RRSIG(
  2087. getCommonRRSIGText("SOA"))));
  2088. return (createContext(options, SUCCESS, soa));
  2089. }
  2090. if (type == RRType::NS()) {
  2091. RRsetPtr ns = textToRRset(origin_.toText() + " 3600 IN NS " +
  2092. Name("ns").concatenate(origin_).toText());
  2093. ns->addRRsig(RdataPtr(new generic::RRSIG(
  2094. getCommonRRSIGText("NS"))));
  2095. return (createContext(options, SUCCESS, ns));
  2096. }
  2097. if (type == RRType::DS()) {
  2098. if (have_ds_) {
  2099. RRsetPtr ds = textToRRset(origin_.toText() +
  2100. " 3600 IN DS 57855 5 1 " +
  2101. "49FD46E6C4B45C55D4AC69CBD"
  2102. "3CD34AC1AFE51DE");
  2103. ds->addRRsig(RdataPtr(new generic::RRSIG(
  2104. getCommonRRSIGText("DS"))));
  2105. return (createContext(options, SUCCESS, ds));
  2106. } else {
  2107. RRsetPtr nsec = textToRRset(origin_.toText() +
  2108. " 3600 IN NSEC " +
  2109. origin_.toText() +
  2110. " SOA NSEC RRSIG");
  2111. nsec->addRRsig(RdataPtr(new generic::RRSIG(
  2112. getCommonRRSIGText("NSEC"))));
  2113. return (createContext(options, NXRRSET, nsec,
  2114. RESULT_NSEC_SIGNED));
  2115. }
  2116. }
  2117. // Returning NXDOMAIN is not correct, but doesn't matter for our tests.
  2118. return (createContext(options, NXDOMAIN, ConstRRsetPtr()));
  2119. }
  2120. private:
  2121. const Name origin_;
  2122. const bool have_ds_;
  2123. };
  2124. TEST_F(QueryTestForMockOnly, dsAboveDelegation) {
  2125. // We could setup the child zone for other data sources, but it won't be
  2126. // simple addition. For now we test it for mock only.
  2127. // Pretending to have authority for the child zone, too.
  2128. mock_client.addZone(ZoneFinderPtr(new AlternateZoneFinder(
  2129. Name("delegation.example.com"))));
  2130. // The following will succeed only if the search goes to the parent
  2131. // zone, not the child one we added above.
  2132. EXPECT_NO_THROW(query.process(*list_,
  2133. Name("delegation.example.com"),
  2134. RRType::DS(), response, true));
  2135. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 4, 6,
  2136. (string(delegation_ds_txt) + "\n" +
  2137. "delegation.example.com. 3600 IN RRSIG " +
  2138. getCommonRRSIGText("DS")).c_str(),
  2139. (string(zone_ns_txt) + "\n" +
  2140. "example.com. 3600 IN RRSIG " +
  2141. getCommonRRSIGText("NS")).c_str(),
  2142. ns_addrs_and_sig_txt.c_str());
  2143. }
  2144. TEST_P(QueryTest, dsAboveDelegationNoData) {
  2145. // Similar to the previous case, but the query is for an unsigned zone
  2146. // (which doesn't have a DS at the parent). The response should be a
  2147. // "no data" error. The query should still be handled at the parent.
  2148. mock_client.addZone(ZoneFinderPtr(
  2149. new AlternateZoneFinder(
  2150. Name("unsigned-delegation.example.com"))));
  2151. // The following will succeed only if the search goes to the parent
  2152. // zone, not the child one we added above.
  2153. EXPECT_NO_THROW(query.process(*list_,
  2154. Name("unsigned-delegation.example.com"),
  2155. RRType::DS(), response, true));
  2156. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2157. (string(soa_minttl_txt) +
  2158. string("example.com. 0 IN RRSIG ") +
  2159. getCommonRRSIGText("SOA") + "\n" +
  2160. string(unsigned_delegation_nsec_txt) +
  2161. "unsigned-delegation.example.com. 3600 IN RRSIG " +
  2162. getCommonRRSIGText("NSEC")).c_str(),
  2163. NULL, mock_finder->getOrigin());
  2164. }
  2165. // This one checks that type-DS query results in a "no data" response
  2166. // when it happens to be sent to the child zone, as described in RFC 4035,
  2167. // section 3.1.4.1. The example is inspired by the B.8. example from the RFC.
  2168. TEST_P(QueryTest, dsBelowDelegation) {
  2169. EXPECT_NO_THROW(query.process(*list_, Name("example.com"),
  2170. RRType::DS(), response, true));
  2171. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2172. (string(soa_minttl_txt) +
  2173. string("example.com. 0 IN RRSIG ") +
  2174. getCommonRRSIGText("SOA") + "\n" +
  2175. string(nsec_apex_txt) + "\n" +
  2176. string("example.com. 3600 IN RRSIG ") +
  2177. getCommonRRSIGText("NSEC")).c_str(), NULL,
  2178. mock_finder->getOrigin());
  2179. }
  2180. // Similar to the previous case, but even more pathological: the DS somehow
  2181. // exists in the child zone. The Query module should still return SOA.
  2182. // In our implementation NSEC/NSEC3 isn't attached in this case.
  2183. TEST_P(QueryTest, dsBelowDelegationWithDS) {
  2184. rrsets_to_add_.push_back(zone_ds_txt);
  2185. addRRsets(rrsets_to_add_, *list_, base_zone_file);
  2186. EXPECT_NO_THROW(query.process(*list_, Name("example.com"),
  2187. RRType::DS(), response, true));
  2188. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 2, 0, NULL,
  2189. (string(soa_minttl_txt) +
  2190. string("example.com. 0 IN RRSIG ") +
  2191. getCommonRRSIGText("SOA")).c_str(), NULL,
  2192. mock_finder->getOrigin());
  2193. }
  2194. // DS query received at a completely irrelevant (neither parent nor child)
  2195. // server. It should just like the "noZone" test case, but DS query involves
  2196. // special processing, so we test it explicitly.
  2197. TEST_P(QueryTest, dsNoZone) {
  2198. query.process(*list_, Name("example"), RRType::DS(), response,
  2199. true);
  2200. responseCheck(response, Rcode::REFUSED(), 0, 0, 0, 0, NULL, NULL, NULL);
  2201. }
  2202. // DS query for a "grandchild" zone. This should result in normal
  2203. // delegation (unless this server also has authority of the grandchild zone).
  2204. TEST_P(QueryTest, dsAtGrandParent) {
  2205. query.process(*list_, Name("grand.delegation.example.com"),
  2206. RRType::DS(), response, true);
  2207. responseCheck(response, Rcode::NOERROR(), 0, 0, 6, 6, NULL,
  2208. (string(delegation_txt) + string(delegation_ds_txt) +
  2209. "delegation.example.com. 3600 IN RRSIG " +
  2210. getCommonRRSIGText("DS")).c_str(),
  2211. ns_addrs_and_sig_txt.c_str());
  2212. }
  2213. // DS query sent to a "grandparent" server that also has authority for the
  2214. // child zone. In this case the query should be handled in the child
  2215. // side and should result in no data with SOA. Note that the server doesn't
  2216. // have authority for the "parent". Unlike the dsAboveDelegation test case
  2217. // the query should be handled in the child zone, not in the grandparent.
  2218. TEST_F(QueryTestForMockOnly, dsAtGrandParentAndChild) {
  2219. // We could setup the child zone for other data sources, but it won't be
  2220. // simple addition. For now we test it for mock only.
  2221. // Pretending to have authority for the child zone, too.
  2222. const Name childname("grand.delegation.example.com");
  2223. mock_client.addZone(ZoneFinderPtr(
  2224. new AlternateZoneFinder(childname)));
  2225. query.process(*list_, childname, RRType::DS(), response, true);
  2226. // Note that RR TTL of SOA and its RRSIG are set to SOA MINTTL, 0
  2227. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2228. (childname.toText() + " 0 IN SOA . . 0 0 0 0 0\n" +
  2229. childname.toText() + " 0 IN RRSIG " +
  2230. getCommonRRSIGText("SOA") + "\n" +
  2231. childname.toText() + " 3600 IN NSEC " +
  2232. childname.toText() + " SOA NSEC RRSIG\n" +
  2233. childname.toText() + " 3600 IN RRSIG " +
  2234. getCommonRRSIGText("NSEC")).c_str(), NULL, childname);
  2235. }
  2236. // DS query for the root name (quite pathological). Since there's no "parent",
  2237. // the query will be handled in the root zone anyway, and should (normally)
  2238. // result in no data.
  2239. TEST_F(QueryTestForMockOnly, dsAtRoot) {
  2240. // We could setup the additional zone for other data sources, but it
  2241. // won't be simple addition. For now we test it for mock only.
  2242. // Pretend to be a root server.
  2243. mock_client.addZone(ZoneFinderPtr(
  2244. new AlternateZoneFinder(Name::ROOT_NAME())));
  2245. query.process(*list_, Name::ROOT_NAME(), RRType::DS(), response,
  2246. true);
  2247. // Note that RR TTL of SOA and its RRSIG are set to SOA MINTTL, 0
  2248. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2249. (string(". 0 IN SOA . . 0 0 0 0 0\n") +
  2250. ". 0 IN RRSIG " + getCommonRRSIGText("SOA") + "\n" +
  2251. ". 3600 IN NSEC " + ". SOA NSEC RRSIG\n" +
  2252. ". 3600 IN RRSIG " +
  2253. getCommonRRSIGText("NSEC")).c_str(), NULL);
  2254. }
  2255. // Even more pathological case: A faked root zone actually has its own DS
  2256. // query. How we respond wouldn't matter much in practice, but check if
  2257. // it behaves as it's intended. This implementation should return the DS.
  2258. TEST_F(QueryTestForMockOnly, dsAtRootWithDS) {
  2259. // We could setup the additional zone for other data sources, but it
  2260. // won't be simple addition. For now we test it for mock only.
  2261. mock_client.addZone(ZoneFinderPtr(
  2262. new AlternateZoneFinder(Name::ROOT_NAME(), true)));
  2263. query.process(*list_, Name::ROOT_NAME(), RRType::DS(), response,
  2264. true);
  2265. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
  2266. (string(". 3600 IN DS 57855 5 1 49FD46E6C4B45C55D4AC69CBD"
  2267. "3CD34AC1AFE51DE\n") +
  2268. ". 3600 IN RRSIG " + getCommonRRSIGText("DS")).c_str(),
  2269. (string(". 3600 IN NS ns.\n") +
  2270. ". 3600 IN RRSIG " + getCommonRRSIGText("NS")).c_str(),
  2271. NULL);
  2272. }
  2273. // Check the signature is present when an NXRRSET is returned
  2274. TEST_P(QueryTest, nxrrsetWithNSEC3) {
  2275. enableNSEC3(rrsets_to_add_);
  2276. // NXRRSET with DNSSEC proof. We should have SOA, NSEC3 that proves the
  2277. // NXRRSET and their RRSIGs.
  2278. query.process(*list_, Name("www.example.com"), RRType::TXT(),
  2279. response, true);
  2280. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2281. (string(soa_minttl_txt) +
  2282. string("example.com. 0 IN RRSIG ") +
  2283. getCommonRRSIGText("SOA") + "\n" +
  2284. string(nsec3_www_txt) + "\n" +
  2285. nsec3_hash_.calculate(Name("www.example.com.")) +
  2286. ".example.com. 3600 IN RRSIG " +
  2287. getCommonRRSIGText("NSEC3") + "\n").c_str(),
  2288. NULL, mock_finder->getOrigin());
  2289. }
  2290. TEST_P(QueryTest, nxrrsetDerivedFromOptOutNSEC3) {
  2291. // In this test we emulate the situation where an empty non-terminal name
  2292. // is derived from insecure delegation and covered by an opt-out NSEC3.
  2293. // In the actual test data the covering NSEC3 really has the opt-out
  2294. // bit set, although the implementation doesn't check it anyway.
  2295. enableNSEC3(rrsets_to_add_);
  2296. query.process(*list_, Name("empty.example.com"), RRType::TXT(), response,
  2297. true);
  2298. // The closest provable encloser is the origin name (example.com.), and
  2299. // the next closer is the empty name itself, which is expected to be
  2300. // covered by an opt-out NSEC3 RR. The response should contain these 2
  2301. // NSEC3s.
  2302. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  2303. (string(soa_minttl_txt) +
  2304. string("example.com. 0 IN RRSIG ") +
  2305. getCommonRRSIGText("SOA") + "\n" +
  2306. string(nsec3_apex_txt) + "\n" +
  2307. nsec3_hash_.calculate(Name("example.com.")) +
  2308. ".example.com. 3600 IN RRSIG " +
  2309. getCommonRRSIGText("NSEC3") + "\n" +
  2310. string(nsec3_www_txt) + "\n" +
  2311. nsec3_hash_.calculate(Name("www.example.com.")) +
  2312. ".example.com. 3600 IN RRSIG " +
  2313. getCommonRRSIGText("NSEC3") + "\n").c_str(),
  2314. NULL, mock_finder->getOrigin());
  2315. }
  2316. TEST_P(QueryTest, nxrrsetWithNSEC3_ds_exact) {
  2317. rrsets_to_add_.push_back(unsigned_delegation_nsec3_txt);
  2318. enableNSEC3(rrsets_to_add_);
  2319. // This delegation has no DS, but does have a matching NSEC3 record
  2320. // (See RFC5155 section 7.2.4)
  2321. query.process(*list_, Name("unsigned-delegation.example.com."),
  2322. RRType::DS(), response, true);
  2323. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
  2324. (string(soa_minttl_txt) +
  2325. string("example.com. 0 IN RRSIG ") +
  2326. getCommonRRSIGText("SOA") + "\n" +
  2327. string(unsigned_delegation_nsec3_txt) + "\n" +
  2328. nsec3_hash_.calculate(
  2329. Name("unsigned-delegation.example.com.")) +
  2330. ".example.com. 3600 IN RRSIG " +
  2331. getCommonRRSIGText("NSEC3") + "\n").c_str(),
  2332. NULL, mock_finder->getOrigin());
  2333. }
  2334. TEST_P(QueryTest, nxrrsetWithNSEC3_ds_no_exact) {
  2335. rrsets_to_add_.push_back(unsigned_delegation_nsec3_txt);
  2336. enableNSEC3(rrsets_to_add_);
  2337. // This delegation has no DS, and no directly matching NSEC3 record
  2338. // So the response should contain closest encloser proof (and the
  2339. // 'next closer' should have opt-out set, though that is not
  2340. // actually checked)
  2341. // (See RFC5155 section 7.2.4)
  2342. query.process(*list_, Name("unsigned-delegation-optout.example.com."),
  2343. RRType::DS(), response, true);
  2344. responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
  2345. (string(soa_minttl_txt) +
  2346. string("example.com. 0 IN RRSIG ") +
  2347. getCommonRRSIGText("SOA") + "\n" +
  2348. string(nsec3_apex_txt) + "\n" +
  2349. nsec3_hash_.calculate(Name("example.com.")) +
  2350. ".example.com. 3600 IN RRSIG " +
  2351. getCommonRRSIGText("NSEC3") + "\n" +
  2352. string(unsigned_delegation_nsec3_txt) + "\n" +
  2353. nsec3_hash_.calculate(
  2354. Name("unsigned-delegation.example.com.")) +
  2355. ".example.com. 3600 IN RRSIG " +
  2356. getCommonRRSIGText("NSEC3") + "\n").c_str(),
  2357. NULL, mock_finder->getOrigin());
  2358. }
  2359. TEST_P(QueryTest, nxdomainWithNSEC3Proof) {
  2360. // Name Error (NXDOMAIN) case with NSEC3 proof per RFC5155 Section 7.2.2.
  2361. // This will be the covering NSEC3 for the next closer
  2362. rrsets_to_add_.push_back(nsec3_uwild_txt);
  2363. // This will be the covering NSEC3 for the possible wildcard
  2364. rrsets_to_add_.push_back(unsigned_delegation_nsec3_txt);
  2365. // Enable NSEC3
  2366. enableNSEC3(rrsets_to_add_);
  2367. query.process(*list_, Name("nxdomain.example.com"), qtype,
  2368. response, true);
  2369. responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 8, 0, NULL,
  2370. // SOA + its RRSIG
  2371. (string(soa_minttl_txt) +
  2372. string("example.com. 0 IN RRSIG ") +
  2373. getCommonRRSIGText("SOA") + "\n" +
  2374. // NSEC3 for the closest encloser + its RRSIG
  2375. string(nsec3_apex_txt) + "\n" +
  2376. nsec3_hash_.calculate(mock_finder->getOrigin()) +
  2377. string(".example.com. 3600 IN RRSIG ") +
  2378. getCommonRRSIGText("NSEC3") + "\n" +
  2379. // NSEC3 for the next closer + its RRSIG
  2380. string(nsec3_uwild_txt) + "\n" +
  2381. nsec3_hash_.calculate(Name("uwild.example.com")) +
  2382. ".example.com. 3600 IN RRSIG " +
  2383. getCommonRRSIGText("NSEC3") + "\n" +
  2384. // NSEC3 for the wildcard + its RRSIG
  2385. string(unsigned_delegation_nsec3_txt) +
  2386. nsec3_hash_.calculate(
  2387. Name("unsigned-delegation.example.com")) +
  2388. ".example.com. 3600 IN RRSIG " +
  2389. getCommonRRSIGText("NSEC3")).c_str(),
  2390. NULL, mock_finder->getOrigin());
  2391. }
  2392. TEST_F(QueryTestForMockOnly, nxdomainWithBadNextNSEC3Proof) {
  2393. // This is a broken data source scenario; works only with mock.
  2394. // Similar to the previous case, but emulating run time collision by
  2395. // returning NULL in the next closer proof for the closest encloser
  2396. // proof.
  2397. mock_finder->setNSEC3Flag(true);
  2398. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  2399. ConstRRsetPtr());
  2400. mock_finder->setNSEC3Result(&nsec3);
  2401. EXPECT_THROW(query.process(*list_, Name("nxdomain.example.com"),
  2402. RRType::TXT(), response, true),
  2403. Query::BadNSEC3);
  2404. }
  2405. TEST_F(QueryTestForMockOnly, nxdomainWithBadWildcardNSEC3Proof) {
  2406. // This is a broken data source scenario; works only with mock.
  2407. // Similar to nxdomainWithNSEC3Proof, but let findNSEC3() return a matching
  2408. // NSEC3 for the possible wildcard name, emulating run-time collision.
  2409. // This should result in BadNSEC3 exception.
  2410. mock_finder->setNSEC3Flag(true);
  2411. mock_finder->addRecord(nsec3_uwild_txt);
  2412. mock_finder->addRecord(unsigned_delegation_nsec3_txt);
  2413. const Name wname("*.example.com");
  2414. ZoneFinder::FindNSEC3Result nsec3(true, 0, textToRRset(nsec3_apex_txt),
  2415. ConstRRsetPtr());
  2416. mock_finder->setNSEC3Result(&nsec3, &wname);
  2417. EXPECT_THROW(query.process(*list_, Name("nxdomain.example.com"), qtype,
  2418. response, true),
  2419. Query::BadNSEC3);
  2420. }
  2421. // The following are tentative tests until we really add tests for the
  2422. // query logic for these cases. At that point it's probably better to
  2423. // clean them up.
  2424. TEST_P(QueryTest, emptyNameWithNSEC3) {
  2425. enableNSEC3(rrsets_to_add_);
  2426. const Name qname("no.example.com");
  2427. ASSERT_TRUE(list_->find(qname).finder_);
  2428. ZoneFinderContextPtr result =
  2429. list_->find(qname).finder_->find(qname, RRType::A(),
  2430. ZoneFinder::FIND_DNSSEC);
  2431. EXPECT_EQ(ZoneFinder::NXRRSET, result->code);
  2432. EXPECT_FALSE(result->rrset);
  2433. EXPECT_TRUE(result->isNSEC3Signed());
  2434. EXPECT_FALSE(result->isWildcard());
  2435. }
  2436. // Vector of RRsets used for the test. Having this external to functions and
  2437. // classes used for the testing simplifies the code.
  2438. std::vector<RRsetPtr> rrset_vector;
  2439. // Callback function for masterLoad.
  2440. void
  2441. loadRRsetVectorCallback(RRsetPtr rrsetptr) {
  2442. rrset_vector.push_back(rrsetptr);
  2443. }
  2444. // Load a set of RRsets into a vector for use in the duplicate RRset test.
  2445. // They don't make a lot of sense as a zone, they are just different. The
  2446. // variables used in the stringstream input have been chosen so that each
  2447. // represents just one RRset.
  2448. void
  2449. loadRRsetVector() {
  2450. stringstream ss;
  2451. // Comments indicate offset in the rrset_vector (when loaded) and the
  2452. // number of RRs in that RRset.
  2453. ss << soa_txt // 0(1)
  2454. << zone_ns_txt // 1(3)
  2455. << delegation_txt // 2(4)
  2456. << delegation_ds_txt // 3(1)
  2457. << mx_txt // 4(3)
  2458. << www_a_txt // 5(1)
  2459. << cname_txt // 6(1)
  2460. << cname_nxdom_txt // 7(1)
  2461. << cname_out_txt; // 8(1)
  2462. rrset_vector.clear();
  2463. masterLoad(ss, Name("example.com."), RRClass::IN(),
  2464. loadRRsetVectorCallback);
  2465. }
  2466. // Note: this is an independent test; don't have to be in the QueryTest
  2467. // fixture.
  2468. TEST(QueryTestSingle, DuplicateNameRemoval) {
  2469. // Load some RRsets into the master vector.
  2470. loadRRsetVector();
  2471. EXPECT_EQ(9, rrset_vector.size());
  2472. // Create an answer, authority and additional vector with some overlapping
  2473. // entries. The following indicate which elements from rrset_vector
  2474. // go into each section vector. (The values have been separated to show
  2475. // the overlap.)
  2476. //
  2477. // answer = 0 1 2 3
  2478. // authority = 2 3 4 5 6 7...
  2479. // ...5 (duplicate in the same section)
  2480. // additional = 0 3 7 8
  2481. //
  2482. // If the duplicate removal works, we should end up with the following in
  2483. // the message created from the three vectors:
  2484. //
  2485. // answer = 0 1 2 3
  2486. // authority = 4 5 6 7
  2487. // additional = 8
  2488. //
  2489. // The expected section into which each RRset is placed is indicated in the
  2490. // array below.
  2491. const Message::Section expected_section[] = {
  2492. Message::SECTION_ANSWER,
  2493. Message::SECTION_ANSWER,
  2494. Message::SECTION_ANSWER,
  2495. Message::SECTION_ANSWER,
  2496. Message::SECTION_AUTHORITY,
  2497. Message::SECTION_AUTHORITY,
  2498. Message::SECTION_AUTHORITY,
  2499. Message::SECTION_AUTHORITY,
  2500. Message::SECTION_ADDITIONAL
  2501. };
  2502. EXPECT_EQ(rrset_vector.size(),
  2503. (sizeof(expected_section) / sizeof(Message::Section)));
  2504. // Create the vectors of RRsets (with the RRsets in a semi-random order).
  2505. std::vector<ConstRRsetPtr> answer;
  2506. answer.insert(answer.end(), rrset_vector.begin() + 2,
  2507. rrset_vector.begin() + 4);
  2508. answer.insert(answer.end(), rrset_vector.begin() + 0,
  2509. rrset_vector.begin() + 2);
  2510. std::vector<ConstRRsetPtr> authority;
  2511. authority.insert(authority.end(), rrset_vector.begin() + 3,
  2512. rrset_vector.begin() + 8);
  2513. authority.push_back(rrset_vector[2]);
  2514. authority.push_back(rrset_vector[5]);
  2515. std::vector<ConstRRsetPtr> additional;
  2516. additional.insert(additional.end(), rrset_vector.begin() + 7,
  2517. rrset_vector.end());
  2518. additional.push_back(rrset_vector[3]);
  2519. additional.push_back(rrset_vector[0]);
  2520. // Create the message object into which the RRsets are put
  2521. Message message(Message::RENDER);
  2522. EXPECT_EQ(0, message.getRRCount(Message::SECTION_ANSWER));
  2523. EXPECT_EQ(0, message.getRRCount(Message::SECTION_AUTHORITY));
  2524. EXPECT_EQ(0, message.getRRCount(Message::SECTION_ADDITIONAL));
  2525. // ... and fill it.
  2526. Query::ResponseCreator().create(message, answer, authority, additional);
  2527. // Check counts in each section. Note that these are RR counts,
  2528. // not RRset counts.
  2529. EXPECT_EQ(9, message.getRRCount(Message::SECTION_ANSWER));
  2530. EXPECT_EQ(6, message.getRRCount(Message::SECTION_AUTHORITY));
  2531. EXPECT_EQ(1, message.getRRCount(Message::SECTION_ADDITIONAL));
  2532. // ... and check that the RRsets are in the correct section
  2533. BOOST_STATIC_ASSERT(Message::SECTION_QUESTION == 0);
  2534. BOOST_STATIC_ASSERT(Message::SECTION_ANSWER == 1);
  2535. BOOST_STATIC_ASSERT(Message::SECTION_AUTHORITY == 2);
  2536. BOOST_STATIC_ASSERT(Message::SECTION_ADDITIONAL == 3);
  2537. Message::Section sections[] = {
  2538. Message::SECTION_QUESTION,
  2539. Message::SECTION_ANSWER,
  2540. Message::SECTION_AUTHORITY,
  2541. Message::SECTION_ADDITIONAL
  2542. };
  2543. for (int section = 1; section <= 3; ++section) {
  2544. for (int vecindex = 0; vecindex < rrset_vector.size(); ++vecindex) {
  2545. // Prepare error message in case an assertion fails (as the default
  2546. // message will only refer to the loop indexes).
  2547. stringstream ss;
  2548. ss << "section " << section << ", name "
  2549. << rrset_vector[vecindex]->getName();
  2550. SCOPED_TRACE(ss.str());
  2551. // Check RRset is in the right section and not in the wrong
  2552. // section.
  2553. if (sections[section] == expected_section[vecindex]) {
  2554. EXPECT_TRUE(message.hasRRset(sections[section],
  2555. rrset_vector[vecindex]));
  2556. } else {
  2557. EXPECT_FALSE(message.hasRRset(sections[section],
  2558. rrset_vector[vecindex]));
  2559. }
  2560. }
  2561. }
  2562. }
  2563. }