auth_srv_unittest.cc 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642
  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 <config.h>
  15. #include <util/io/sockaddr_util.h>
  16. #include <dns/message.h>
  17. #include <dns/messagerenderer.h>
  18. #include <dns/name.h>
  19. #include <dns/opcode.h>
  20. #include <dns/rrclass.h>
  21. #include <dns/rrtype.h>
  22. #include <dns/rrttl.h>
  23. #include <dns/rdataclass.h>
  24. #include <dns/tsig.h>
  25. #include <server_common/portconfig.h>
  26. #include <server_common/keyring.h>
  27. #include <datasrc/memory_datasrc.h>
  28. #include <auth/auth_srv.h>
  29. #include <auth/common.h>
  30. #include <auth/statistics.h>
  31. #include <util/unittests/mock_socketsession.h>
  32. #include <dns/tests/unittest_util.h>
  33. #include <testutils/dnsmessage_test.h>
  34. #include <testutils/srv_test.h>
  35. #include <testutils/mockups.h>
  36. #include <testutils/portconfig.h>
  37. #include <testutils/socket_request.h>
  38. #include <gtest/gtest.h>
  39. #include <boost/lexical_cast.hpp>
  40. #include <boost/shared_ptr.hpp>
  41. #include <boost/scoped_ptr.hpp>
  42. #include <vector>
  43. #include <sys/types.h>
  44. #include <sys/socket.h>
  45. #include <netdb.h>
  46. using namespace std;
  47. using namespace isc::cc;
  48. using namespace isc::dns;
  49. using namespace isc::util;
  50. using namespace isc::util::io::internal;
  51. using namespace isc::util::unittests;
  52. using namespace isc::dns::rdata;
  53. using namespace isc::data;
  54. using namespace isc::xfr;
  55. using namespace isc::asiodns;
  56. using namespace isc::asiolink;
  57. using namespace isc::testutils;
  58. using namespace isc::server_common::portconfig;
  59. using isc::UnitTestUtil;
  60. using boost::scoped_ptr;
  61. namespace {
  62. const char* const CONFIG_TESTDB =
  63. "{\"database_file\": \"" TEST_DATA_DIR "/example.sqlite3\"}";
  64. // The following file must be non existent and must be non"creatable" (see
  65. // the sqlite3 test).
  66. const char* const BADCONFIG_TESTDB =
  67. "{ \"database_file\": \"" TEST_DATA_DIR "/nodir/notexist\"}";
  68. // This is a configuration that uses the in-memory data source containing
  69. // a signed example zone.
  70. const char* const CONFIG_INMEMORY_EXAMPLE =
  71. "{\"datasources\": [{\"type\": \"memory\","
  72. "\"zones\": [{\"origin\": \"example\","
  73. "\"file\": \"" TEST_DATA_DIR "/rfc5155-example.zone.signed\"}]}]}";
  74. class AuthSrvTest : public SrvTestBase {
  75. protected:
  76. AuthSrvTest() :
  77. dnss_(),
  78. server(true, xfrout, ddns_forwarder),
  79. rrclass(RRClass::IN()),
  80. // The empty string is expected value of the parameter of
  81. // requestSocket, not the app_name (there's no fallback, it checks
  82. // the empty string is passed).
  83. sock_requestor_(dnss_, address_store_, 53210, "")
  84. {
  85. server.setDNSService(dnss_);
  86. server.setXfrinSession(&notify_session);
  87. server.setStatisticsSession(&statistics_session);
  88. }
  89. ~AuthSrvTest() {
  90. // Clear the message now; depending on the RTTI implementation,
  91. // type information may be lost if the message is cleared
  92. // automatically later, so as a precaution we do it now.
  93. parse_message->clear(Message::PARSE);
  94. }
  95. virtual void processMessage() {
  96. // If processMessage has been called before, parse_message needs
  97. // to be reset. If it hasn't, there's no harm in doing so
  98. parse_message->clear(Message::PARSE);
  99. server.processMessage(*io_message, *parse_message, *response_obuffer,
  100. &dnsserv);
  101. }
  102. // Helper for checking Rcode statistic counters;
  103. // Checks for one specific Rcode statistics counter value
  104. void checkRcodeCounter(const Rcode& rcode, int expected_value) const {
  105. EXPECT_EQ(expected_value, server.getCounter(rcode)) <<
  106. "Expected Rcode count for " << rcode.toText() <<
  107. " " << expected_value << ", was: " <<
  108. server.getCounter(rcode);
  109. }
  110. // Checks whether all Rcode counters are set to zero
  111. void checkAllRcodeCountersZero() const {
  112. for (int i = 0; i < 17; i++) {
  113. checkRcodeCounter(Rcode(i), 0);
  114. }
  115. }
  116. // Checks whether all Rcode counters are set to zero except the given
  117. // rcode (it is checked to be set to 'value')
  118. void checkAllRcodeCountersZeroExcept(const Rcode& rcode, int value) const {
  119. for (int i = 0; i < 17; i++) {
  120. const Rcode rc(i);
  121. if (rc == rcode) {
  122. checkRcodeCounter(Rcode(i), value);
  123. } else {
  124. checkRcodeCounter(Rcode(i), 0);
  125. }
  126. }
  127. }
  128. // Convenience method for tests that expect to return SERVFAIL
  129. // It calls processMessage, checks if there is an answer, and
  130. // check the header for default SERVFAIL data
  131. void processAndCheckSERVFAIL() {
  132. processMessage();
  133. EXPECT_TRUE(dnsserv.hasAnswer());
  134. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  135. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  136. }
  137. // Convenient shortcut of creating a simple request and having the
  138. // server process it.
  139. void createAndSendRequest(RRType req_type, Opcode opcode = Opcode::QUERY(),
  140. const Name& req_name = Name("example.com"),
  141. RRClass req_class = RRClass::IN(),
  142. int protocol = IPPROTO_UDP,
  143. const char* const remote_address =
  144. DEFAULT_REMOTE_ADDRESS,
  145. uint16_t remote_port = DEFAULT_REMOTE_PORT)
  146. {
  147. UnitTestUtil::createRequestMessage(request_message, opcode,
  148. default_qid, req_name,
  149. req_class, req_type);
  150. createRequestPacket(request_message, protocol, NULL,
  151. remote_address, remote_port);
  152. parse_message->clear(Message::PARSE);
  153. server.processMessage(*io_message, *parse_message, *response_obuffer,
  154. &dnsserv);
  155. }
  156. MockDNSService dnss_;
  157. MockSession statistics_session;
  158. MockXfroutClient xfrout;
  159. MockSocketSessionForwarder ddns_forwarder;
  160. AuthSrv server;
  161. const RRClass rrclass;
  162. vector<uint8_t> response_data;
  163. AddressList address_store_;
  164. TestSocketRequestor sock_requestor_;
  165. };
  166. // A helper function that builds a response to version.bind/TXT/CH that
  167. // should be identical to the response from our builtin (static) data source
  168. // by default. The resulting wire-format data will be stored in 'data'.
  169. void
  170. createBuiltinVersionResponse(const qid_t qid, vector<uint8_t>& data) {
  171. const Name version_name("version.bind");
  172. Message message(Message::RENDER);
  173. UnitTestUtil::createRequestMessage(message, Opcode::QUERY(),
  174. qid, version_name,
  175. RRClass::CH(), RRType::TXT());
  176. message.setHeaderFlag(Message::HEADERFLAG_QR);
  177. message.setHeaderFlag(Message::HEADERFLAG_AA);
  178. RRsetPtr rrset_version = RRsetPtr(new RRset(version_name, RRClass::CH(),
  179. RRType::TXT(), RRTTL(0)));
  180. rrset_version->addRdata(generic::TXT(PACKAGE_STRING));
  181. message.addRRset(Message::SECTION_ANSWER, rrset_version);
  182. RRsetPtr rrset_version_ns = RRsetPtr(new RRset(version_name, RRClass::CH(),
  183. RRType::NS(), RRTTL(0)));
  184. rrset_version_ns->addRdata(generic::NS(version_name));
  185. message.addRRset(Message::SECTION_AUTHORITY, rrset_version_ns);
  186. MessageRenderer renderer;
  187. message.toWire(renderer);
  188. data.clear();
  189. data.assign(static_cast<const uint8_t*>(renderer.getData()),
  190. static_cast<const uint8_t*>(renderer.getData()) +
  191. renderer.getLength());
  192. }
  193. // In the following tests we confirm the response data is rendered in
  194. // wire format in the expected way.
  195. // The most primitive check: checking the result of the processMessage()
  196. // method
  197. TEST_F(AuthSrvTest, builtInQuery) {
  198. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  199. default_qid, Name("version.bind"),
  200. RRClass::CH(), RRType::TXT());
  201. createRequestPacket(request_message, IPPROTO_UDP);
  202. server.processMessage(*io_message, *parse_message, *response_obuffer,
  203. &dnsserv);
  204. createBuiltinVersionResponse(default_qid, response_data);
  205. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  206. response_obuffer->getData(),
  207. response_obuffer->getLength(),
  208. &response_data[0], response_data.size());
  209. checkAllRcodeCountersZeroExcept(Rcode::NOERROR(), 1);
  210. }
  211. // Same test emulating the UDPServer class behavior (defined in libasiolink).
  212. // This is not a good test in that it assumes internal implementation details
  213. // of UDPServer, but we've encountered a regression due to the introduction
  214. // of that class, so we add a test for that case to prevent such a regression
  215. // in future.
  216. // Besides, the generalization of UDPServer is probably too much for the
  217. // authoritative only server in terms of performance, and it's quite likely
  218. // we need to drop it for the authoritative server implementation.
  219. // At that point we can drop this test, too.
  220. TEST_F(AuthSrvTest, builtInQueryViaDNSServer) {
  221. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  222. default_qid, Name("version.bind"),
  223. RRClass::CH(), RRType::TXT());
  224. createRequestPacket(request_message, IPPROTO_UDP);
  225. (*server.getDNSLookupProvider())(*io_message, parse_message,
  226. response_message,
  227. response_obuffer, &dnsserv);
  228. (*server.getDNSAnswerProvider())(*io_message, parse_message,
  229. response_message, response_obuffer);
  230. createBuiltinVersionResponse(default_qid, response_data);
  231. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  232. response_obuffer->getData(),
  233. response_obuffer->getLength(),
  234. &response_data[0], response_data.size());
  235. }
  236. // Same type of test as builtInQueryViaDNSServer but for an error response.
  237. TEST_F(AuthSrvTest, iqueryViaDNSServer) {
  238. createDataFromFile("iquery_fromWire.wire");
  239. (*server.getDNSLookupProvider())(*io_message, parse_message,
  240. response_message,
  241. response_obuffer, &dnsserv);
  242. (*server.getDNSAnswerProvider())(*io_message, parse_message,
  243. response_message, response_obuffer);
  244. UnitTestUtil::readWireData("iquery_response_fromWire.wire",
  245. response_data);
  246. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  247. response_obuffer->getData(),
  248. response_obuffer->getLength(),
  249. &response_data[0], response_data.size());
  250. }
  251. // Unsupported requests. Should result in NOTIMP.
  252. TEST_F(AuthSrvTest, unsupportedRequest) {
  253. unsupportedRequest();
  254. // unsupportedRequest tries 13 different opcodes
  255. checkAllRcodeCountersZeroExcept(Rcode::NOTIMP(), 13);
  256. }
  257. // Multiple questions. Should result in FORMERR.
  258. TEST_F(AuthSrvTest, multiQuestion) {
  259. multiQuestion();
  260. checkAllRcodeCountersZeroExcept(Rcode::FORMERR(), 1);
  261. }
  262. // Incoming data doesn't even contain the complete header. Must be silently
  263. // dropped.
  264. TEST_F(AuthSrvTest, shortMessage) {
  265. shortMessage();
  266. checkAllRcodeCountersZero();
  267. }
  268. // Response messages. Must be silently dropped, whether it's a valid response
  269. // or malformed or could otherwise cause a protocol error.
  270. TEST_F(AuthSrvTest, response) {
  271. response();
  272. checkAllRcodeCountersZero();
  273. }
  274. // Query with a broken question
  275. TEST_F(AuthSrvTest, shortQuestion) {
  276. shortQuestion();
  277. checkAllRcodeCountersZeroExcept(Rcode::FORMERR(), 1);
  278. }
  279. // Query with a broken answer section
  280. TEST_F(AuthSrvTest, shortAnswer) {
  281. shortAnswer();
  282. checkAllRcodeCountersZeroExcept(Rcode::FORMERR(), 1);
  283. }
  284. // Query with unsupported version of EDNS.
  285. TEST_F(AuthSrvTest, ednsBadVers) {
  286. ednsBadVers();
  287. checkAllRcodeCountersZeroExcept(Rcode::BADVERS(), 1);
  288. }
  289. TEST_F(AuthSrvTest, AXFROverUDP) {
  290. axfrOverUDP();
  291. }
  292. TEST_F(AuthSrvTest, AXFRSuccess) {
  293. EXPECT_FALSE(xfrout.isConnected());
  294. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  295. Name("example.com"), RRClass::IN(),
  296. RRType::AXFR());
  297. createRequestPacket(request_message, IPPROTO_TCP);
  298. // On success, the AXFR query has been passed to a separate process,
  299. // so we shouldn't have to respond.
  300. server.processMessage(*io_message, *parse_message, *response_obuffer,
  301. &dnsserv);
  302. EXPECT_FALSE(dnsserv.hasAnswer());
  303. EXPECT_TRUE(xfrout.isConnected());
  304. checkAllRcodeCountersZero();
  305. }
  306. // Try giving the server a TSIG signed request and see it can anwer signed as
  307. // well
  308. TEST_F(AuthSrvTest, TSIGSigned) {
  309. // Prepare key, the client message, etc
  310. const TSIGKey key("key:c2VjcmV0Cg==:hmac-sha1");
  311. TSIGContext context(key);
  312. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  313. Name("version.bind"), RRClass::CH(),
  314. RRType::TXT());
  315. createRequestPacket(request_message, IPPROTO_UDP, &context);
  316. // Run the message through the server
  317. boost::shared_ptr<TSIGKeyRing> keyring(new TSIGKeyRing);
  318. keyring->add(key);
  319. server.setTSIGKeyRing(&keyring);
  320. server.processMessage(*io_message, *parse_message, *response_obuffer,
  321. &dnsserv);
  322. // What did we get?
  323. EXPECT_TRUE(dnsserv.hasAnswer());
  324. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  325. opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 1, 0);
  326. // We need to parse the message ourself, or getTSIGRecord won't work
  327. InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength());
  328. Message m(Message::PARSE);
  329. m.fromWire(ib);
  330. const TSIGRecord* tsig = m.getTSIGRecord();
  331. ASSERT_TRUE(tsig != NULL) << "Missing TSIG signature";
  332. TSIGError error(context.verify(tsig, response_obuffer->getData(),
  333. response_obuffer->getLength()));
  334. EXPECT_EQ(TSIGError::NOERROR(), error) <<
  335. "The server signed the response, but it doesn't seem to be valid";
  336. checkAllRcodeCountersZeroExcept(Rcode::NOERROR(), 1);
  337. }
  338. // Give the server a signed request, but don't give it the key. It will
  339. // not be able to verify it, returning BADKEY
  340. TEST_F(AuthSrvTest, TSIGSignedBadKey) {
  341. TSIGKey key("key:c2VjcmV0Cg==:hmac-sha1");
  342. TSIGContext context(key);
  343. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  344. Name("version.bind"), RRClass::CH(),
  345. RRType::TXT());
  346. createRequestPacket(request_message, IPPROTO_UDP, &context);
  347. // Process the message, but use a different key there
  348. boost::shared_ptr<TSIGKeyRing> keyring(new TSIGKeyRing);
  349. server.setTSIGKeyRing(&keyring);
  350. server.processMessage(*io_message, *parse_message, *response_obuffer,
  351. &dnsserv);
  352. EXPECT_TRUE(dnsserv.hasAnswer());
  353. headerCheck(*parse_message, default_qid, TSIGError::BAD_KEY().toRcode(),
  354. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  355. // We need to parse the message ourself, or getTSIGRecord won't work
  356. InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength());
  357. Message m(Message::PARSE);
  358. m.fromWire(ib);
  359. const TSIGRecord* tsig = m.getTSIGRecord();
  360. ASSERT_TRUE(tsig != NULL) <<
  361. "Missing TSIG signature (we should have one even at error)";
  362. EXPECT_EQ(TSIGError::BAD_KEY_CODE, tsig->getRdata().getError());
  363. EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
  364. "It should be unsigned with this error";
  365. checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
  366. }
  367. // Give the server a signed request, but signed by a different key
  368. // (with the same name). It should return BADSIG
  369. TEST_F(AuthSrvTest, TSIGBadSig) {
  370. TSIGKey key("key:c2VjcmV0Cg==:hmac-sha1");
  371. TSIGContext context(key);
  372. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  373. Name("version.bind"), RRClass::CH(),
  374. RRType::TXT());
  375. createRequestPacket(request_message, IPPROTO_UDP, &context);
  376. // Process the message, but use a different key there
  377. boost::shared_ptr<TSIGKeyRing> keyring(new TSIGKeyRing);
  378. keyring->add(TSIGKey("key:QkFECg==:hmac-sha1"));
  379. server.setTSIGKeyRing(&keyring);
  380. server.processMessage(*io_message, *parse_message, *response_obuffer,
  381. &dnsserv);
  382. EXPECT_TRUE(dnsserv.hasAnswer());
  383. headerCheck(*parse_message, default_qid, TSIGError::BAD_SIG().toRcode(),
  384. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  385. // We need to parse the message ourself, or getTSIGRecord won't work
  386. InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength());
  387. Message m(Message::PARSE);
  388. m.fromWire(ib);
  389. const TSIGRecord* tsig = m.getTSIGRecord();
  390. ASSERT_TRUE(tsig != NULL) <<
  391. "Missing TSIG signature (we should have one even at error)";
  392. EXPECT_EQ(TSIGError::BAD_SIG_CODE, tsig->getRdata().getError());
  393. EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
  394. "It should be unsigned with this error";
  395. checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
  396. }
  397. // Give the server a signed unsupported request with a bad signature.
  398. // This checks the server first verifies the signature before anything
  399. // else.
  400. TEST_F(AuthSrvTest, TSIGCheckFirst) {
  401. TSIGKey key("key:c2VjcmV0Cg==:hmac-sha1");
  402. TSIGContext context(key);
  403. // Pass a wrong opcode there. The server shouldn't know what to do
  404. // about it.
  405. UnitTestUtil::createRequestMessage(request_message, Opcode::RESERVED14(),
  406. default_qid, Name("version.bind"),
  407. RRClass::CH(), RRType::TXT());
  408. createRequestPacket(request_message, IPPROTO_UDP, &context);
  409. // Process the message, but use a different key there
  410. boost::shared_ptr<TSIGKeyRing> keyring(new TSIGKeyRing);
  411. keyring->add(TSIGKey("key:QkFECg==:hmac-sha1"));
  412. server.setTSIGKeyRing(&keyring);
  413. server.processMessage(*io_message, *parse_message, *response_obuffer,
  414. &dnsserv);
  415. EXPECT_TRUE(dnsserv.hasAnswer());
  416. headerCheck(*parse_message, default_qid, TSIGError::BAD_SIG().toRcode(),
  417. Opcode::RESERVED14().getCode(), QR_FLAG, 0, 0, 0, 0);
  418. // We need to parse the message ourself, or getTSIGRecord won't work
  419. InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength());
  420. Message m(Message::PARSE);
  421. m.fromWire(ib);
  422. const TSIGRecord* tsig = m.getTSIGRecord();
  423. ASSERT_TRUE(tsig != NULL) <<
  424. "Missing TSIG signature (we should have one even at error)";
  425. EXPECT_EQ(TSIGError::BAD_SIG_CODE, tsig->getRdata().getError());
  426. EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
  427. "It should be unsigned with this error";
  428. // TSIG should have failed, and so the per opcode counter shouldn't be
  429. // incremented.
  430. EXPECT_EQ(0, server.getCounter(Opcode::RESERVED14()));
  431. checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
  432. }
  433. TEST_F(AuthSrvTest, AXFRConnectFail) {
  434. EXPECT_FALSE(xfrout.isConnected()); // check prerequisite
  435. xfrout.disableConnect();
  436. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  437. Name("example.com"), RRClass::IN(),
  438. RRType::AXFR());
  439. createRequestPacket(request_message, IPPROTO_TCP);
  440. server.processMessage(*io_message, *parse_message, *response_obuffer,
  441. &dnsserv);
  442. EXPECT_TRUE(dnsserv.hasAnswer());
  443. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  444. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  445. EXPECT_FALSE(xfrout.isConnected());
  446. }
  447. TEST_F(AuthSrvTest, AXFRSendFail) {
  448. // first send a valid query, making the connection with the xfr process
  449. // open.
  450. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  451. Name("example.com"), RRClass::IN(),
  452. RRType::AXFR());
  453. createRequestPacket(request_message, IPPROTO_TCP);
  454. server.processMessage(*io_message, *parse_message, *response_obuffer,
  455. &dnsserv);
  456. EXPECT_TRUE(xfrout.isConnected());
  457. xfrout.disableSend();
  458. parse_message->clear(Message::PARSE);
  459. response_obuffer->clear();
  460. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  461. Name("example.com"), RRClass::IN(),
  462. RRType::AXFR());
  463. createRequestPacket(request_message, IPPROTO_TCP);
  464. server.processMessage(*io_message, *parse_message, *response_obuffer,
  465. &dnsserv);
  466. EXPECT_TRUE(dnsserv.hasAnswer());
  467. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  468. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  469. // The connection should have been closed due to the send failure.
  470. EXPECT_FALSE(xfrout.isConnected());
  471. }
  472. TEST_F(AuthSrvTest, AXFRDisconnectFail) {
  473. // In our usage disconnect() shouldn't fail. But even if it does,
  474. // it should not disrupt service (so processMessage should have caught it)
  475. xfrout.disableSend();
  476. xfrout.disableDisconnect();
  477. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  478. Name("example.com"), RRClass::IN(),
  479. RRType::AXFR());
  480. createRequestPacket(request_message, IPPROTO_TCP);
  481. EXPECT_NO_THROW(server.processMessage(*io_message, *parse_message,
  482. *response_obuffer, &dnsserv));
  483. // Since the disconnect failed, we should still be 'connected'
  484. EXPECT_TRUE(xfrout.isConnected());
  485. // XXX: we need to re-enable disconnect. otherwise an exception would be
  486. // thrown via the destructor of the server.
  487. xfrout.enableDisconnect();
  488. }
  489. TEST_F(AuthSrvTest, IXFRConnectFail) {
  490. EXPECT_FALSE(xfrout.isConnected()); // check prerequisite
  491. xfrout.disableConnect();
  492. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  493. Name("example.com"), RRClass::IN(),
  494. RRType::IXFR());
  495. createRequestPacket(request_message, IPPROTO_TCP);
  496. server.processMessage(*io_message, *parse_message, *response_obuffer,
  497. &dnsserv);
  498. EXPECT_TRUE(dnsserv.hasAnswer());
  499. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  500. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  501. EXPECT_FALSE(xfrout.isConnected());
  502. }
  503. TEST_F(AuthSrvTest, IXFRSendFail) {
  504. // first send a valid query, making the connection with the xfr process
  505. // open.
  506. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  507. Name("example.com"), RRClass::IN(),
  508. RRType::IXFR());
  509. createRequestPacket(request_message, IPPROTO_TCP);
  510. server.processMessage(*io_message, *parse_message, *response_obuffer,
  511. &dnsserv);
  512. EXPECT_TRUE(xfrout.isConnected());
  513. xfrout.disableSend();
  514. parse_message->clear(Message::PARSE);
  515. response_obuffer->clear();
  516. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  517. Name("example.com"), RRClass::IN(),
  518. RRType::IXFR());
  519. createRequestPacket(request_message, IPPROTO_TCP);
  520. server.processMessage(*io_message, *parse_message, *response_obuffer,
  521. &dnsserv);
  522. EXPECT_TRUE(dnsserv.hasAnswer());
  523. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  524. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  525. // The connection should have been closed due to the send failure.
  526. EXPECT_FALSE(xfrout.isConnected());
  527. }
  528. TEST_F(AuthSrvTest, IXFRDisconnectFail) {
  529. // In our usage disconnect() shouldn't fail, but even if it does,
  530. // procesMessage() should catch it.
  531. xfrout.disableSend();
  532. xfrout.disableDisconnect();
  533. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  534. Name("example.com"), RRClass::IN(),
  535. RRType::IXFR());
  536. createRequestPacket(request_message, IPPROTO_TCP);
  537. EXPECT_NO_THROW(server.processMessage(*io_message, *parse_message,
  538. *response_obuffer, &dnsserv));
  539. EXPECT_TRUE(xfrout.isConnected());
  540. // XXX: we need to re-enable disconnect. otherwise an exception would be
  541. // thrown via the destructor of the server.
  542. xfrout.enableDisconnect();
  543. }
  544. TEST_F(AuthSrvTest, notify) {
  545. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  546. default_qid, Name("example.com"),
  547. RRClass::IN(), RRType::SOA());
  548. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  549. createRequestPacket(request_message, IPPROTO_UDP);
  550. server.processMessage(*io_message, *parse_message, *response_obuffer,
  551. &dnsserv);
  552. EXPECT_TRUE(dnsserv.hasAnswer());
  553. // An internal command message should have been created and sent to an
  554. // external module. Check them.
  555. EXPECT_EQ("Zonemgr", notify_session.getMessageDest());
  556. EXPECT_EQ("notify",
  557. notify_session.getSentMessage()->get("command")->get(0)->stringValue());
  558. ConstElementPtr notify_args =
  559. notify_session.getSentMessage()->get("command")->get(1);
  560. EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
  561. EXPECT_EQ(DEFAULT_REMOTE_ADDRESS,
  562. notify_args->get("master")->stringValue());
  563. EXPECT_EQ("IN", notify_args->get("zone_class")->stringValue());
  564. // On success, the server should return a response to the notify.
  565. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  566. Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
  567. // The question must be identical to that of the received notify
  568. ConstQuestionPtr question = *parse_message->beginQuestion();
  569. EXPECT_EQ(Name("example.com"), question->getName());
  570. EXPECT_EQ(RRClass::IN(), question->getClass());
  571. EXPECT_EQ(RRType::SOA(), question->getType());
  572. checkAllRcodeCountersZeroExcept(Rcode::NOERROR(), 1);
  573. }
  574. TEST_F(AuthSrvTest, notifyForCHClass) {
  575. // Same as the previous test, but for the CH RRClass.
  576. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  577. default_qid, Name("example.com"),
  578. RRClass::CH(), RRType::SOA());
  579. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  580. createRequestPacket(request_message, IPPROTO_UDP);
  581. server.processMessage(*io_message, *parse_message, *response_obuffer,
  582. &dnsserv);
  583. EXPECT_TRUE(dnsserv.hasAnswer());
  584. // Other conditions should be the same, so simply confirm the RR class is
  585. // set correctly.
  586. ConstElementPtr notify_args =
  587. notify_session.getSentMessage()->get("command")->get(1);
  588. EXPECT_EQ("CH", notify_args->get("zone_class")->stringValue());
  589. }
  590. TEST_F(AuthSrvTest, notifyEmptyQuestion) {
  591. request_message.clear(Message::RENDER);
  592. request_message.setOpcode(Opcode::NOTIFY());
  593. request_message.setRcode(Rcode::NOERROR());
  594. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  595. request_message.setQid(default_qid);
  596. request_message.toWire(request_renderer);
  597. createRequestPacket(request_message, IPPROTO_UDP);
  598. server.processMessage(*io_message, *parse_message, *response_obuffer,
  599. &dnsserv);
  600. EXPECT_TRUE(dnsserv.hasAnswer());
  601. headerCheck(*parse_message, default_qid, Rcode::FORMERR(),
  602. Opcode::NOTIFY().getCode(), QR_FLAG, 0, 0, 0, 0);
  603. }
  604. TEST_F(AuthSrvTest, notifyMultiQuestions) {
  605. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  606. default_qid, Name("example.com"),
  607. RRClass::IN(), RRType::SOA());
  608. // add one more SOA question
  609. request_message.addQuestion(Question(Name("example.com"), RRClass::IN(),
  610. RRType::SOA()));
  611. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  612. createRequestPacket(request_message, IPPROTO_UDP);
  613. server.processMessage(*io_message, *parse_message, *response_obuffer,
  614. &dnsserv);
  615. EXPECT_TRUE(dnsserv.hasAnswer());
  616. headerCheck(*parse_message, default_qid, Rcode::FORMERR(),
  617. Opcode::NOTIFY().getCode(), QR_FLAG, 2, 0, 0, 0);
  618. }
  619. TEST_F(AuthSrvTest, notifyNonSOAQuestion) {
  620. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  621. default_qid, Name("example.com"),
  622. RRClass::IN(), RRType::NS());
  623. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  624. createRequestPacket(request_message, IPPROTO_UDP);
  625. server.processMessage(*io_message, *parse_message, *response_obuffer,
  626. &dnsserv);
  627. EXPECT_TRUE(dnsserv.hasAnswer());
  628. headerCheck(*parse_message, default_qid, Rcode::FORMERR(),
  629. Opcode::NOTIFY().getCode(), QR_FLAG, 1, 0, 0, 0);
  630. }
  631. TEST_F(AuthSrvTest, notifyWithoutAA) {
  632. // implicitly leave the AA bit off. our implementation will accept it.
  633. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  634. default_qid, Name("example.com"),
  635. RRClass::IN(), RRType::SOA());
  636. createRequestPacket(request_message, IPPROTO_UDP);
  637. server.processMessage(*io_message, *parse_message, *response_obuffer,
  638. &dnsserv);
  639. EXPECT_TRUE(dnsserv.hasAnswer());
  640. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  641. Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
  642. }
  643. TEST_F(AuthSrvTest, notifyWithErrorRcode) {
  644. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  645. default_qid, Name("example.com"),
  646. RRClass::IN(), RRType::SOA());
  647. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  648. request_message.setRcode(Rcode::SERVFAIL());
  649. createRequestPacket(request_message, IPPROTO_UDP);
  650. server.processMessage(*io_message, *parse_message, *response_obuffer,
  651. &dnsserv);
  652. EXPECT_TRUE(dnsserv.hasAnswer());
  653. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  654. Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
  655. }
  656. TEST_F(AuthSrvTest, notifyWithoutSession) {
  657. server.setXfrinSession(NULL);
  658. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  659. default_qid, Name("example.com"),
  660. RRClass::IN(), RRType::SOA());
  661. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  662. createRequestPacket(request_message, IPPROTO_UDP);
  663. // we simply ignore the notify and let it be resent if an internal error
  664. // happens.
  665. server.processMessage(*io_message, *parse_message, *response_obuffer,
  666. &dnsserv);
  667. EXPECT_FALSE(dnsserv.hasAnswer());
  668. }
  669. TEST_F(AuthSrvTest, notifySendFail) {
  670. notify_session.disableSend();
  671. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  672. default_qid, Name("example.com"),
  673. RRClass::IN(), RRType::SOA());
  674. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  675. createRequestPacket(request_message, IPPROTO_UDP);
  676. server.processMessage(*io_message, *parse_message, *response_obuffer,
  677. &dnsserv);
  678. EXPECT_FALSE(dnsserv.hasAnswer());
  679. }
  680. TEST_F(AuthSrvTest, notifyReceiveFail) {
  681. notify_session.disableReceive();
  682. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  683. default_qid, Name("example.com"),
  684. RRClass::IN(), RRType::SOA());
  685. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  686. createRequestPacket(request_message, IPPROTO_UDP);
  687. server.processMessage(*io_message, *parse_message, *response_obuffer,
  688. &dnsserv);
  689. EXPECT_FALSE(dnsserv.hasAnswer());
  690. }
  691. TEST_F(AuthSrvTest, notifyWithBogusSessionMessage) {
  692. notify_session.setMessage(Element::fromJSON("{\"foo\": 1}"));
  693. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  694. default_qid, Name("example.com"),
  695. RRClass::IN(), RRType::SOA());
  696. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  697. createRequestPacket(request_message, IPPROTO_UDP);
  698. server.processMessage(*io_message, *parse_message, *response_obuffer,
  699. &dnsserv);
  700. EXPECT_FALSE(dnsserv.hasAnswer());
  701. }
  702. TEST_F(AuthSrvTest, notifyWithSessionMessageError) {
  703. notify_session.setMessage(
  704. Element::fromJSON("{\"result\": [1, \"FAIL\"]}"));
  705. UnitTestUtil::createRequestMessage(request_message, Opcode::NOTIFY(),
  706. default_qid, Name("example.com"),
  707. RRClass::IN(), RRType::SOA());
  708. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  709. createRequestPacket(request_message, IPPROTO_UDP);
  710. server.processMessage(*io_message, *parse_message, *response_obuffer,
  711. &dnsserv);
  712. EXPECT_FALSE(dnsserv.hasAnswer());
  713. }
  714. void
  715. updateConfig(AuthSrv* server, const char* const config_data,
  716. const bool expect_success)
  717. {
  718. ConstElementPtr config_answer =
  719. server->updateConfig(Element::fromJSON(config_data));
  720. EXPECT_EQ(Element::map, config_answer->getType());
  721. EXPECT_TRUE(config_answer->contains("result"));
  722. ConstElementPtr result = config_answer->get("result");
  723. EXPECT_EQ(Element::list, result->getType());
  724. EXPECT_EQ(expect_success ? 0 : 1, result->get(0)->intValue()) <<
  725. "Bad result from updateConfig: " << result->str();
  726. }
  727. // Install a Sqlite3 data source with testing data.
  728. TEST_F(AuthSrvTest, updateConfig) {
  729. updateConfig(&server, CONFIG_TESTDB, true);
  730. // query for existent data in the installed data source. The resulting
  731. // response should have the AA flag on, and have an RR in each answer
  732. // and authority section.
  733. createDataFromFile("examplequery_fromWire.wire");
  734. server.processMessage(*io_message, *parse_message, *response_obuffer,
  735. &dnsserv);
  736. EXPECT_TRUE(dnsserv.hasAnswer());
  737. headerCheck(*parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
  738. QR_FLAG | AA_FLAG, 1, 1, 1, 0);
  739. }
  740. TEST_F(AuthSrvTest, datasourceFail) {
  741. updateConfig(&server, CONFIG_TESTDB, true);
  742. // This query will hit a corrupted entry of the data source (the zoneload
  743. // tool and the data source itself naively accept it). This will result
  744. // in a SERVFAIL response, and the answer and authority sections should
  745. // be empty.
  746. createDataFromFile("badExampleQuery_fromWire.wire");
  747. server.processMessage(*io_message, *parse_message, *response_obuffer,
  748. &dnsserv);
  749. EXPECT_TRUE(dnsserv.hasAnswer());
  750. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  751. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  752. }
  753. TEST_F(AuthSrvTest, updateConfigFail) {
  754. // First, load a valid data source.
  755. updateConfig(&server, CONFIG_TESTDB, true);
  756. // Next, try to update it with a non-existent one. This should fail.
  757. updateConfig(&server, BADCONFIG_TESTDB, false);
  758. // The original data source should still exist.
  759. createDataFromFile("examplequery_fromWire.wire");
  760. server.processMessage(*io_message, *parse_message, *response_obuffer,
  761. &dnsserv);
  762. EXPECT_TRUE(dnsserv.hasAnswer());
  763. headerCheck(*parse_message, default_qid, Rcode::NOERROR(), opcode.getCode(),
  764. QR_FLAG | AA_FLAG, 1, 1, 1, 0);
  765. }
  766. TEST_F(AuthSrvTest,
  767. #ifdef USE_STATIC_LINK
  768. DISABLED_updateWithInMemoryClient
  769. #else
  770. updateWithInMemoryClient
  771. #endif
  772. )
  773. {
  774. // Test configuring memory data source. Detailed test cases are covered
  775. // in the configuration tests. We only check the AuthSrv interface here.
  776. // By default memory data source isn't enabled
  777. EXPECT_FALSE(server.hasInMemoryClient());
  778. updateConfig(&server,
  779. "{\"datasources\": [{\"type\": \"memory\"}]}", true);
  780. // after successful configuration, we should have one (with empty zoneset).
  781. EXPECT_TRUE(server.hasInMemoryClient());
  782. EXPECT_EQ(0, server.getInMemoryClient(rrclass)->getZoneCount());
  783. // The memory data source is empty, should return REFUSED rcode.
  784. createDataFromFile("examplequery_fromWire.wire");
  785. server.processMessage(*io_message, *parse_message, *response_obuffer,
  786. &dnsserv);
  787. EXPECT_TRUE(dnsserv.hasAnswer());
  788. headerCheck(*parse_message, default_qid, Rcode::REFUSED(),
  789. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  790. }
  791. TEST_F(AuthSrvTest,
  792. #ifdef USE_STATIC_LINK
  793. DISABLED_queryWithInMemoryClientNoDNSSEC
  794. #else
  795. queryWithInMemoryClientNoDNSSEC
  796. #endif
  797. )
  798. {
  799. // In this example, we do simple check that query is handled from the
  800. // query handler class, and confirm it returns no error and a non empty
  801. // answer section. Detailed examination on the response content
  802. // for various types of queries are tested in the query tests.
  803. updateConfig(&server, CONFIG_INMEMORY_EXAMPLE, true);
  804. EXPECT_TRUE(server.hasInMemoryClient());
  805. EXPECT_EQ(1, server.getInMemoryClient(rrclass)->getZoneCount());
  806. createDataFromFile("nsec3query_nodnssec_fromWire.wire");
  807. server.processMessage(*io_message, *parse_message, *response_obuffer,
  808. &dnsserv);
  809. EXPECT_TRUE(dnsserv.hasAnswer());
  810. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  811. opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 2, 1);
  812. }
  813. TEST_F(AuthSrvTest,
  814. #ifdef USE_STATIC_LINK
  815. DISABLED_queryWithInMemoryClientDNSSEC
  816. #else
  817. queryWithInMemoryClientDNSSEC
  818. #endif
  819. )
  820. {
  821. // Similar to the previous test, but the query has the DO bit on.
  822. // The response should contain RRSIGs, and should have more RRs than
  823. // the previous case.
  824. updateConfig(&server, CONFIG_INMEMORY_EXAMPLE, true);
  825. EXPECT_TRUE(server.hasInMemoryClient());
  826. EXPECT_EQ(1, server.getInMemoryClient(rrclass)->getZoneCount());
  827. createDataFromFile("nsec3query_fromWire.wire");
  828. server.processMessage(*io_message, *parse_message, *response_obuffer,
  829. &dnsserv);
  830. EXPECT_TRUE(dnsserv.hasAnswer());
  831. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  832. opcode.getCode(), QR_FLAG | AA_FLAG, 1, 2, 3, 3);
  833. }
  834. TEST_F(AuthSrvTest,
  835. #ifdef USE_STATIC_LINK
  836. DISABLED_chQueryWithInMemoryClient
  837. #else
  838. chQueryWithInMemoryClient
  839. #endif
  840. )
  841. {
  842. // Configure memory data source for class IN
  843. updateConfig(&server, "{\"datasources\": "
  844. "[{\"class\": \"IN\", \"type\": \"memory\"}]}", true);
  845. // This shouldn't affect the result of class CH query
  846. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  847. default_qid, Name("version.bind"),
  848. RRClass::CH(), RRType::TXT());
  849. createRequestPacket(request_message, IPPROTO_UDP);
  850. server.processMessage(*io_message, *parse_message, *response_obuffer,
  851. &dnsserv);
  852. EXPECT_TRUE(dnsserv.hasAnswer());
  853. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  854. opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 1, 0);
  855. }
  856. TEST_F(AuthSrvTest, cacheSlots) {
  857. // simple check for the get/set operations
  858. server.setCacheSlots(10); // 10 = arbitrary choice
  859. EXPECT_EQ(10, server.getCacheSlots());
  860. // 0 is a valid size
  861. server.setCacheSlots(0);
  862. EXPECT_EQ(00, server.getCacheSlots());
  863. }
  864. // Submit UDP normal query and check query counter
  865. TEST_F(AuthSrvTest, queryCounterUDPNormal) {
  866. // The counter should be initialized to 0.
  867. EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_UDP_QUERY));
  868. // Create UDP message and process.
  869. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  870. default_qid, Name("example.com"),
  871. RRClass::IN(), RRType::NS());
  872. createRequestPacket(request_message, IPPROTO_UDP);
  873. server.processMessage(*io_message, *parse_message, *response_obuffer,
  874. &dnsserv);
  875. // After processing UDP query, the counter should be 1.
  876. EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_UDP_QUERY));
  877. // The counter for opcode Query should also be one
  878. EXPECT_EQ(1, server.getCounter(Opcode::QUERY()));
  879. // The counter for REFUSED responses should also be one, the rest zero
  880. checkAllRcodeCountersZeroExcept(Rcode::REFUSED(), 1);
  881. }
  882. // Submit TCP normal query and check query counter
  883. TEST_F(AuthSrvTest, queryCounterTCPNormal) {
  884. // The counter should be initialized to 0.
  885. EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
  886. // Create TCP message and process.
  887. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  888. default_qid, Name("example.com"),
  889. RRClass::IN(), RRType::NS());
  890. createRequestPacket(request_message, IPPROTO_TCP);
  891. server.processMessage(*io_message, *parse_message, *response_obuffer,
  892. &dnsserv);
  893. // After processing TCP query, the counter should be 1.
  894. EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
  895. // The counter for SUCCESS responses should also be one
  896. EXPECT_EQ(1, server.getCounter(Opcode::QUERY()));
  897. // The counter for REFUSED responses should also be one, the rest zero
  898. checkAllRcodeCountersZeroExcept(Rcode::REFUSED(), 1);
  899. }
  900. // Submit TCP AXFR query and check query counter
  901. TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
  902. // The counter should be initialized to 0.
  903. EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
  904. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  905. Name("example.com"), RRClass::IN(), RRType::AXFR());
  906. createRequestPacket(request_message, IPPROTO_TCP);
  907. // On success, the AXFR query has been passed to a separate process,
  908. // so auth itself shouldn't respond.
  909. server.processMessage(*io_message, *parse_message, *response_obuffer,
  910. &dnsserv);
  911. EXPECT_FALSE(dnsserv.hasAnswer());
  912. // After processing TCP AXFR query, the counter should be 1.
  913. EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
  914. // No rcodes should be incremented
  915. checkAllRcodeCountersZero();
  916. }
  917. // Submit TCP IXFR query and check query counter
  918. TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
  919. // The counter should be initialized to 0.
  920. EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
  921. UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
  922. Name("example.com"), RRClass::IN(), RRType::IXFR());
  923. createRequestPacket(request_message, IPPROTO_TCP);
  924. // On success, the IXFR query has been passed to a separate process,
  925. // so auth itself shouldn't respond.
  926. server.processMessage(*io_message, *parse_message, *response_obuffer,
  927. &dnsserv);
  928. EXPECT_FALSE(dnsserv.hasAnswer());
  929. // After processing TCP IXFR query, the counter should be 1.
  930. EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
  931. }
  932. TEST_F(AuthSrvTest, queryCounterOpcodes) {
  933. for (int i = 0; i < 16; ++i) {
  934. // The counter should be initialized to 0.
  935. EXPECT_EQ(0, server.getCounter(Opcode(i)));
  936. // For each possible opcode, create a request message and send it
  937. UnitTestUtil::createRequestMessage(request_message, Opcode(i),
  938. default_qid, Name("example.com"),
  939. RRClass::IN(), RRType::NS());
  940. createRequestPacket(request_message, IPPROTO_UDP);
  941. // "send" the request N-th times where N is i + 1 for i-th code.
  942. // we intentionally use different values for each code
  943. for (int j = 0; j <= i; ++j) {
  944. parse_message->clear(Message::PARSE);
  945. server.processMessage(*io_message, *parse_message,
  946. *response_obuffer,
  947. &dnsserv);
  948. }
  949. // Confirm the counter.
  950. EXPECT_EQ(i + 1, server.getCounter(Opcode(i)));
  951. }
  952. }
  953. // class for queryCounterUnexpected test
  954. // getProtocol() returns IPPROTO_IP
  955. class DummyUnknownSocket : public IOSocket {
  956. public:
  957. DummyUnknownSocket() {}
  958. virtual int getNative() const { return (0); }
  959. virtual int getProtocol() const { return (IPPROTO_IP); }
  960. };
  961. // function for queryCounterUnexpected test
  962. // returns a reference to a static object of DummyUnknownSocket
  963. IOSocket&
  964. getDummyUnknownSocket() {
  965. static DummyUnknownSocket socket;
  966. return (socket);
  967. }
  968. // Submit unexpected type of query and check it is ignored
  969. TEST_F(AuthSrvTest, queryCounterUnexpected) {
  970. // This code isn't exception safe, but we'd rather keep the code
  971. // simpler and more readable as this is only for tests
  972. // Create UDP query packet.
  973. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  974. default_qid, Name("example.com"),
  975. RRClass::IN(), RRType::NS());
  976. createRequestPacket(request_message, IPPROTO_UDP);
  977. // Modify the message.
  978. delete io_message;
  979. endpoint = IOEndpoint::create(IPPROTO_UDP,
  980. IOAddress(DEFAULT_REMOTE_ADDRESS), 53210);
  981. io_message = new IOMessage(request_renderer.getData(),
  982. request_renderer.getLength(),
  983. getDummyUnknownSocket(), *endpoint);
  984. EXPECT_FALSE(dnsserv.hasAnswer());
  985. }
  986. TEST_F(AuthSrvTest, stop) {
  987. // normal case is covered in command_unittest.cc. we should primarily
  988. // test it here, but the current design of the stop test takes time,
  989. // so we consolidate the cases in the command tests.
  990. // If/when the interval timer has finer granularity we'll probably add
  991. // our own tests here, so we keep this empty test case.
  992. }
  993. TEST_F(AuthSrvTest, listenAddresses) {
  994. isc::testutils::portconfig::listenAddresses(server);
  995. // Check it requests the correct addresses
  996. const char* tokens[] = {
  997. "TCP:127.0.0.1:53210:1",
  998. "UDP:127.0.0.1:53210:2",
  999. "TCP:::1:53210:3",
  1000. "UDP:::1:53210:4",
  1001. NULL
  1002. };
  1003. sock_requestor_.checkTokens(tokens, sock_requestor_.given_tokens_,
  1004. "Given tokens");
  1005. // It returns back to empty set of addresses afterwards, so
  1006. // they should be released
  1007. sock_requestor_.checkTokens(tokens, sock_requestor_.released_tokens_,
  1008. "Released tokens");
  1009. }
  1010. TEST_F(AuthSrvTest, processNormalQuery_reuseRenderer1) {
  1011. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  1012. default_qid, Name("example.com"),
  1013. RRClass::IN(), RRType::NS());
  1014. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  1015. createRequestPacket(request_message, IPPROTO_UDP);
  1016. server.processMessage(*io_message, *parse_message, *response_obuffer,
  1017. &dnsserv);
  1018. EXPECT_NE(request_message.getRcode(), parse_message->getRcode());
  1019. }
  1020. TEST_F(AuthSrvTest, processNormalQuery_reuseRenderer2) {
  1021. UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
  1022. default_qid, Name("example.com"),
  1023. RRClass::IN(), RRType::SOA());
  1024. request_message.setHeaderFlag(Message::HEADERFLAG_AA);
  1025. createRequestPacket(request_message, IPPROTO_UDP);
  1026. server.processMessage(*io_message, *parse_message, *response_obuffer,
  1027. &dnsserv);
  1028. ConstQuestionPtr question = *parse_message->beginQuestion();
  1029. EXPECT_STRNE(question->getType().toText().c_str(),
  1030. RRType::NS().toText().c_str());
  1031. }
  1032. //
  1033. // Tests for catching exceptions in various stages of the query processing
  1034. //
  1035. // These tests work by defining two proxy classes, that act as an in-memory
  1036. // client by default, but can throw exceptions at various points.
  1037. //
  1038. namespace {
  1039. /// The possible methods to throw in, either in FakeClient or
  1040. /// FakeZoneFinder
  1041. enum ThrowWhen {
  1042. THROW_NEVER,
  1043. THROW_AT_FIND_ZONE,
  1044. THROW_AT_GET_ORIGIN,
  1045. THROW_AT_GET_CLASS,
  1046. THROW_AT_FIND,
  1047. THROW_AT_FIND_ALL,
  1048. THROW_AT_FIND_NSEC3
  1049. };
  1050. /// convenience function to check whether and what to throw
  1051. void
  1052. checkThrow(ThrowWhen method, ThrowWhen throw_at, bool isc_exception) {
  1053. if (method == throw_at) {
  1054. if (isc_exception) {
  1055. isc_throw(isc::Exception, "foo");
  1056. } else {
  1057. throw std::exception();
  1058. }
  1059. }
  1060. }
  1061. /// \brief proxy class for the ZoneFinder returned by the Client
  1062. /// proxied by FakeClient
  1063. ///
  1064. /// See the documentation for FakeClient for more information,
  1065. /// all methods simply check whether they should throw, and if not, call
  1066. /// their proxied equivalent.
  1067. class FakeZoneFinder : public isc::datasrc::ZoneFinder {
  1068. public:
  1069. FakeZoneFinder(isc::datasrc::ZoneFinderPtr zone_finder,
  1070. ThrowWhen throw_when, bool isc_exception,
  1071. ConstRRsetPtr fake_rrset) :
  1072. real_zone_finder_(zone_finder),
  1073. throw_when_(throw_when),
  1074. isc_exception_(isc_exception),
  1075. fake_rrset_(fake_rrset)
  1076. {}
  1077. virtual isc::dns::Name
  1078. getOrigin() const {
  1079. checkThrow(THROW_AT_GET_ORIGIN, throw_when_, isc_exception_);
  1080. return (real_zone_finder_->getOrigin());
  1081. }
  1082. virtual isc::dns::RRClass
  1083. getClass() const {
  1084. checkThrow(THROW_AT_GET_CLASS, throw_when_, isc_exception_);
  1085. return (real_zone_finder_->getClass());
  1086. }
  1087. virtual isc::datasrc::ZoneFinderContextPtr
  1088. find(const isc::dns::Name& name,
  1089. const isc::dns::RRType& type,
  1090. isc::datasrc::ZoneFinder::FindOptions options)
  1091. {
  1092. using namespace isc::datasrc;
  1093. checkThrow(THROW_AT_FIND, throw_when_, isc_exception_);
  1094. // If faked RRset was specified on construction and it matches the
  1095. // query, return it instead of searching the real data source.
  1096. if (fake_rrset_ && fake_rrset_->getName() == name &&
  1097. fake_rrset_->getType() == type)
  1098. {
  1099. return (ZoneFinderContextPtr(new ZoneFinder::Context(
  1100. *this, options,
  1101. ResultContext(SUCCESS,
  1102. fake_rrset_))));
  1103. }
  1104. return (real_zone_finder_->find(name, type, options));
  1105. }
  1106. virtual isc::datasrc::ZoneFinderContextPtr
  1107. findAll(const isc::dns::Name& name,
  1108. std::vector<isc::dns::ConstRRsetPtr> &target,
  1109. const FindOptions options = FIND_DEFAULT)
  1110. {
  1111. checkThrow(THROW_AT_FIND_ALL, throw_when_, isc_exception_);
  1112. return (real_zone_finder_->findAll(name, target, options));
  1113. }
  1114. virtual FindNSEC3Result
  1115. findNSEC3(const isc::dns::Name& name, bool recursive) {
  1116. checkThrow(THROW_AT_FIND_NSEC3, throw_when_, isc_exception_);
  1117. return (real_zone_finder_->findNSEC3(name, recursive));
  1118. }
  1119. private:
  1120. isc::datasrc::ZoneFinderPtr real_zone_finder_;
  1121. ThrowWhen throw_when_;
  1122. bool isc_exception_;
  1123. ConstRRsetPtr fake_rrset_;
  1124. };
  1125. /// \brief Proxy FakeClient that can throw exceptions at specified times
  1126. ///
  1127. /// Currently it is used as an 'InMemoryClient' using setInMemoryClient,
  1128. /// but it is in effect a general datasource client.
  1129. class FakeClient : public isc::datasrc::DataSourceClient {
  1130. public:
  1131. /// \brief Create a proxy memory client
  1132. ///
  1133. /// \param real_client The real (in-memory) client to proxy
  1134. /// \param throw_when if set to any value other than never, that is
  1135. /// the method that will throw an exception (either in this
  1136. /// class or the related FakeZoneFinder)
  1137. /// \param isc_exception if true, throw isc::Exception, otherwise,
  1138. /// throw std::exception
  1139. /// \param fake_rrset If non NULL, it will be used as an answer to
  1140. /// find() for that name and type.
  1141. FakeClient(isc::datasrc::DataSourceClientContainerPtr real_client,
  1142. ThrowWhen throw_when, bool isc_exception,
  1143. ConstRRsetPtr fake_rrset = ConstRRsetPtr()) :
  1144. real_client_ptr_(real_client),
  1145. throw_when_(throw_when),
  1146. isc_exception_(isc_exception),
  1147. fake_rrset_(fake_rrset)
  1148. {}
  1149. /// \brief proxy call for findZone
  1150. ///
  1151. /// if this instance was constructed with throw_when set to find_zone,
  1152. /// this method will throw. Otherwise, it will return a FakeZoneFinder
  1153. /// instance which will throw at the method specified at the
  1154. /// construction of this instance.
  1155. virtual FindResult
  1156. findZone(const isc::dns::Name& name) const {
  1157. checkThrow(THROW_AT_FIND_ZONE, throw_when_, isc_exception_);
  1158. const FindResult result =
  1159. real_client_ptr_->getInstance().findZone(name);
  1160. return (FindResult(result.code, isc::datasrc::ZoneFinderPtr(
  1161. new FakeZoneFinder(result.zone_finder,
  1162. throw_when_,
  1163. isc_exception_,
  1164. fake_rrset_))));
  1165. }
  1166. isc::datasrc::ZoneUpdaterPtr
  1167. getUpdater(const isc::dns::Name&, bool, bool) const {
  1168. isc_throw(isc::NotImplemented,
  1169. "Update attempt on in fake data source");
  1170. }
  1171. std::pair<isc::datasrc::ZoneJournalReader::Result,
  1172. isc::datasrc::ZoneJournalReaderPtr>
  1173. getJournalReader(const isc::dns::Name&, uint32_t, uint32_t) const {
  1174. isc_throw(isc::NotImplemented, "Journaling isn't supported for "
  1175. "fake data source");
  1176. }
  1177. private:
  1178. const isc::datasrc::DataSourceClientContainerPtr real_client_ptr_;
  1179. ThrowWhen throw_when_;
  1180. bool isc_exception_;
  1181. ConstRRsetPtr fake_rrset_;
  1182. };
  1183. class FakeContainer : public isc::datasrc::DataSourceClientContainer {
  1184. public:
  1185. /// \brief Creates a fake container for the given in-memory client
  1186. ///
  1187. /// The initializer creates a fresh instance of a memory datasource,
  1188. /// which is ignored for the rest (but we do not allow 'null' containers
  1189. /// atm, and this is only needed in these tests, this may be changed
  1190. /// if we generalize the container class a bit more)
  1191. ///
  1192. /// It will also create a FakeClient, with the given arguments, which
  1193. /// is actually used when the instance is requested.
  1194. FakeContainer(isc::datasrc::DataSourceClientContainerPtr real_client,
  1195. ThrowWhen throw_when, bool isc_exception,
  1196. ConstRRsetPtr fake_rrset = ConstRRsetPtr()) :
  1197. DataSourceClientContainer("memory",
  1198. Element::fromJSON("{\"type\": \"memory\"}")),
  1199. client_(new FakeClient(real_client, throw_when, isc_exception,
  1200. fake_rrset))
  1201. {}
  1202. isc::datasrc::DataSourceClient& getInstance() {
  1203. return (*client_);
  1204. }
  1205. private:
  1206. const boost::scoped_ptr<isc::datasrc::DataSourceClient> client_;
  1207. };
  1208. } // end anonymous namespace for throwing proxy classes
  1209. // Test for the tests
  1210. //
  1211. // Set the proxies to never throw, this should have the same result as
  1212. // queryWithInMemoryClientNoDNSSEC, and serves to test the two proxy classes
  1213. TEST_F(AuthSrvTest,
  1214. #ifdef USE_STATIC_LINK
  1215. DISABLED_queryWithInMemoryClientProxy
  1216. #else
  1217. queryWithInMemoryClientProxy
  1218. #endif
  1219. )
  1220. {
  1221. // Set real inmem client to proxy
  1222. updateConfig(&server, CONFIG_INMEMORY_EXAMPLE, true);
  1223. EXPECT_TRUE(server.hasInMemoryClient());
  1224. isc::datasrc::DataSourceClientContainerPtr fake_client_container(
  1225. new FakeContainer(server.getInMemoryClientContainer(rrclass),
  1226. THROW_NEVER, false));
  1227. server.setInMemoryClient(rrclass, fake_client_container);
  1228. createDataFromFile("nsec3query_nodnssec_fromWire.wire");
  1229. server.processMessage(*io_message, *parse_message, *response_obuffer,
  1230. &dnsserv);
  1231. EXPECT_TRUE(dnsserv.hasAnswer());
  1232. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  1233. opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 2, 1);
  1234. }
  1235. // Convenience function for the rest of the tests, set up a proxy
  1236. // to throw in the given method
  1237. // If isc_exception is true, it will throw isc::Exception, otherwise
  1238. // it will throw std::exception
  1239. // If non null rrset is given, it will be passed to the proxy so it can
  1240. // return some faked response.
  1241. void
  1242. setupThrow(AuthSrv* server, const char *config, ThrowWhen throw_when,
  1243. bool isc_exception, ConstRRsetPtr rrset = ConstRRsetPtr())
  1244. {
  1245. // Set real inmem client to proxy
  1246. updateConfig(server, config, true);
  1247. // Set it to throw on findZone(), this should result in
  1248. // SERVFAIL on any exception
  1249. isc::datasrc::DataSourceClientContainerPtr fake_client_container(
  1250. new FakeContainer(
  1251. server->getInMemoryClientContainer(isc::dns::RRClass::IN()),
  1252. throw_when, isc_exception, rrset));
  1253. ASSERT_TRUE(server->hasInMemoryClient());
  1254. server->setInMemoryClient(isc::dns::RRClass::IN(), fake_client_container);
  1255. }
  1256. TEST_F(AuthSrvTest,
  1257. #ifdef USE_STATIC_LINK
  1258. DISABLED_queryWithThrowingProxyServfails
  1259. #else
  1260. queryWithThrowingProxyServfails
  1261. #endif
  1262. )
  1263. {
  1264. // Test the common cases, all of which should simply return SERVFAIL
  1265. // Use THROW_NEVER as end marker
  1266. ThrowWhen throws[] = { THROW_AT_FIND_ZONE,
  1267. THROW_AT_GET_ORIGIN,
  1268. THROW_AT_FIND,
  1269. THROW_AT_FIND_NSEC3,
  1270. THROW_NEVER };
  1271. UnitTestUtil::createDNSSECRequestMessage(request_message, opcode,
  1272. default_qid, Name("foo.example."),
  1273. RRClass::IN(), RRType::TXT());
  1274. for (ThrowWhen* when(throws); *when != THROW_NEVER; ++when) {
  1275. createRequestPacket(request_message, IPPROTO_UDP);
  1276. setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, *when, true);
  1277. processAndCheckSERVFAIL();
  1278. // To be sure, check same for non-isc-exceptions
  1279. createRequestPacket(request_message, IPPROTO_UDP);
  1280. setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, *when, false);
  1281. processAndCheckSERVFAIL();
  1282. }
  1283. }
  1284. // Throw isc::Exception in getClass(). (Currently?) getClass is not called
  1285. // in the processMessage path, so this should result in a normal answer
  1286. TEST_F(AuthSrvTest,
  1287. #ifdef USE_STATIC_LINK
  1288. DISABLED_queryWithInMemoryClientProxyGetClass
  1289. #else
  1290. queryWithInMemoryClientProxyGetClass
  1291. #endif
  1292. )
  1293. {
  1294. createDataFromFile("nsec3query_nodnssec_fromWire.wire");
  1295. setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, THROW_AT_GET_CLASS, true);
  1296. // getClass is not called so it should just answer
  1297. server.processMessage(*io_message, *parse_message, *response_obuffer,
  1298. &dnsserv);
  1299. EXPECT_TRUE(dnsserv.hasAnswer());
  1300. headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
  1301. opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 2, 1);
  1302. }
  1303. TEST_F(AuthSrvTest,
  1304. #ifdef USE_STATIC_LINK
  1305. DISABLED_queryWithThrowingInToWire
  1306. #else
  1307. queryWithThrowingInToWire
  1308. #endif
  1309. )
  1310. {
  1311. // Set up a faked data source. It will return an empty RRset for the
  1312. // query.
  1313. ConstRRsetPtr empty_rrset(new RRset(Name("foo.example"),
  1314. RRClass::IN(), RRType::TXT(),
  1315. RRTTL(0)));
  1316. setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, THROW_NEVER, true,
  1317. empty_rrset);
  1318. // Repeat the query processing two times. Due to the faked RRset,
  1319. // toWire() should throw, and it should result in SERVFAIL.
  1320. OutputBufferPtr orig_buffer;
  1321. for (int i = 0; i < 2; ++i) {
  1322. UnitTestUtil::createDNSSECRequestMessage(request_message, opcode,
  1323. default_qid,
  1324. Name("foo.example."),
  1325. RRClass::IN(), RRType::TXT());
  1326. createRequestPacket(request_message, IPPROTO_UDP);
  1327. server.processMessage(*io_message, *parse_message, *response_obuffer,
  1328. &dnsserv);
  1329. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  1330. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  1331. // Make a backup of the original buffer for latest tests and replace
  1332. // it with a new one
  1333. if (!orig_buffer) {
  1334. orig_buffer = response_obuffer;
  1335. response_obuffer.reset(new OutputBuffer(0));
  1336. }
  1337. request_message.clear(Message::RENDER);
  1338. parse_message->clear(Message::PARSE);
  1339. }
  1340. // Now check if the original buffer is intact
  1341. parse_message->clear(Message::PARSE);
  1342. InputBuffer ibuffer(orig_buffer->getData(), orig_buffer->getLength());
  1343. parse_message->fromWire(ibuffer);
  1344. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  1345. opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
  1346. }
  1347. //
  1348. // DDNS related tests
  1349. //
  1350. // Helper subroutine to check if the given socket address has the expected
  1351. // address and port. It depends on specific output of getnameinfo() (while
  1352. // there can be multiple textual representation of the same address) but
  1353. // in practice it should be reliable.
  1354. void
  1355. checkAddrPort(const struct sockaddr& actual_sa,
  1356. const string& expected_addr, uint16_t expected_port)
  1357. {
  1358. char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
  1359. const int error = getnameinfo(&actual_sa, getSALength(actual_sa), hbuf,
  1360. sizeof(hbuf), sbuf, sizeof(sbuf),
  1361. NI_NUMERICHOST | NI_NUMERICSERV);
  1362. if (error != 0) {
  1363. isc_throw(isc::Unexpected, "getnameinfo failed: " <<
  1364. gai_strerror(error));
  1365. }
  1366. EXPECT_EQ(expected_addr, hbuf);
  1367. EXPECT_EQ(boost::lexical_cast<string>(expected_port), sbuf);
  1368. }
  1369. TEST_F(AuthSrvTest, DDNSForward) {
  1370. EXPECT_FALSE(ddns_forwarder.isConnected());
  1371. // Repeat sending an update request 4 times, differing some network
  1372. // parameters: UDP/IPv4, TCP/IPv4, UDP/IPv6, TCP/IPv6, in this order.
  1373. // By doing that we can also confirm the forwarder connection will be
  1374. // established exactly once, and kept established.
  1375. for (size_t i = 0; i < 4; ++i) {
  1376. // Use different names for some different cases
  1377. const Name zone_name = Name(i < 2 ? "example.com" : "example.org");
  1378. const socklen_t family = (i < 2) ? AF_INET : AF_INET6;
  1379. const char* const remote_addr =
  1380. (family == AF_INET) ? "192.0.2.1" : "2001:db8::1";
  1381. const uint16_t remote_port =
  1382. (family == AF_INET) ? 53214 : 53216;
  1383. const int protocol = ((i % 2) == 0) ? IPPROTO_UDP : IPPROTO_TCP;
  1384. createAndSendRequest(RRType::SOA(), Opcode::UPDATE(), zone_name,
  1385. RRClass::IN(), protocol, remote_addr,
  1386. remote_port);
  1387. EXPECT_FALSE(dnsserv.hasAnswer());
  1388. EXPECT_TRUE(ddns_forwarder.isConnected());
  1389. // Examine the pushed data (note: currently "local end" has a dummy
  1390. // value equal to remote)
  1391. EXPECT_EQ(family, ddns_forwarder.getPushedFamily());
  1392. const int expected_type =
  1393. (protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
  1394. EXPECT_EQ(expected_type, ddns_forwarder.getPushedType());
  1395. EXPECT_EQ(protocol, ddns_forwarder.getPushedProtocol());
  1396. checkAddrPort(ddns_forwarder.getPushedRemoteend(),
  1397. remote_addr, remote_port);
  1398. checkAddrPort(ddns_forwarder.getPushedLocalend(),
  1399. remote_addr, remote_port);
  1400. EXPECT_EQ(io_message->getDataSize(),
  1401. ddns_forwarder.getPushedData().size());
  1402. EXPECT_EQ(0, memcmp(io_message->getData(),
  1403. &ddns_forwarder.getPushedData()[0],
  1404. ddns_forwarder.getPushedData().size()));
  1405. }
  1406. }
  1407. TEST_F(AuthSrvTest, DDNSForwardConnectFail) {
  1408. // make connect attempt fail. It should result in SERVFAIL. Note that
  1409. // the question (zone) section should be cleared for opcode of update.
  1410. ddns_forwarder.disableConnect();
  1411. createAndSendRequest(RRType::SOA(), Opcode::UPDATE());
  1412. EXPECT_TRUE(dnsserv.hasAnswer());
  1413. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  1414. Opcode::UPDATE().getCode(), QR_FLAG, 0, 0, 0, 0);
  1415. EXPECT_FALSE(ddns_forwarder.isConnected());
  1416. // Now make connect okay again. Despite the previous failure the new
  1417. // connection should now be established.
  1418. ddns_forwarder.enableConnect();
  1419. createAndSendRequest(RRType::SOA(), Opcode::UPDATE());
  1420. EXPECT_FALSE(dnsserv.hasAnswer());
  1421. EXPECT_TRUE(ddns_forwarder.isConnected());
  1422. }
  1423. TEST_F(AuthSrvTest, DDNSForwardPushFail) {
  1424. // Make first request succeed, which will establish the connection.
  1425. EXPECT_FALSE(ddns_forwarder.isConnected());
  1426. createAndSendRequest(RRType::SOA(), Opcode::UPDATE());
  1427. EXPECT_TRUE(ddns_forwarder.isConnected());
  1428. // make connect attempt fail. It should result in SERVFAIL. The
  1429. // connection should be closed. Use IPv6 address for varying log output.
  1430. ddns_forwarder.disablePush();
  1431. createAndSendRequest(RRType::SOA(), Opcode::UPDATE(), Name("example.com"),
  1432. RRClass::IN(), IPPROTO_UDP, "2001:db8::2");
  1433. EXPECT_TRUE(dnsserv.hasAnswer());
  1434. headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
  1435. Opcode::UPDATE().getCode(), QR_FLAG, 0, 0, 0, 0);
  1436. EXPECT_FALSE(ddns_forwarder.isConnected());
  1437. // Allow push again. Connection will be reopened, and the request will
  1438. // be forwarded successfully.
  1439. ddns_forwarder.enablePush();
  1440. createAndSendRequest(RRType::SOA(), Opcode::UPDATE());
  1441. EXPECT_FALSE(dnsserv.hasAnswer());
  1442. EXPECT_TRUE(ddns_forwarder.isConnected());
  1443. }
  1444. TEST_F(AuthSrvTest, DDNSForwardClose) {
  1445. scoped_ptr<AuthSrv> tmp_server(new AuthSrv(true, xfrout, ddns_forwarder));
  1446. UnitTestUtil::createRequestMessage(request_message, Opcode::UPDATE(),
  1447. default_qid, Name("example.com"),
  1448. RRClass::IN(), RRType::SOA());
  1449. createRequestPacket(request_message, IPPROTO_UDP);
  1450. tmp_server->processMessage(*io_message, *parse_message, *response_obuffer,
  1451. &dnsserv);
  1452. EXPECT_FALSE(dnsserv.hasAnswer());
  1453. EXPECT_TRUE(ddns_forwarder.isConnected());
  1454. // Destroy the server. The forwarder should close the connection.
  1455. tmp_server.reset();
  1456. EXPECT_FALSE(ddns_forwarder.isConnected());
  1457. }
  1458. }