auth_srv_unittest.cc 71 KB

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