tsig_unittest.cc 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. // Copyright (C) 2011 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 <time.h>
  15. #include <string>
  16. #include <stdexcept>
  17. #include <vector>
  18. #include <boost/scoped_ptr.hpp>
  19. #include <gtest/gtest.h>
  20. #include <exceptions/exceptions.h>
  21. #include <util/buffer.h>
  22. #include <util/encode/base64.h>
  23. #include <util/unittests/newhook.h>
  24. #include <util/time_utilities.h>
  25. #include <dns/message.h>
  26. #include <dns/messagerenderer.h>
  27. #include <dns/question.h>
  28. #include <dns/opcode.h>
  29. #include <dns/rcode.h>
  30. #include <dns/rrclass.h>
  31. #include <dns/rrtype.h>
  32. #include <dns/tsig.h>
  33. #include <dns/tsigkey.h>
  34. #include <dns/tsigrecord.h>
  35. #include <dns/tests/unittest_util.h>
  36. using namespace std;
  37. using namespace isc;
  38. using namespace isc::dns;
  39. using namespace isc::util;
  40. using namespace isc::util::encode;
  41. using namespace isc::dns::rdata;
  42. using isc::UnitTestUtil;
  43. // See dnssectime.cc
  44. namespace isc {
  45. namespace util {
  46. namespace detail {
  47. extern int64_t (*gettimeFunction)();
  48. }
  49. }
  50. }
  51. namespace {
  52. // See dnssectime_unittest.cc
  53. template <int64_t NOW>
  54. int64_t
  55. testGetTime() {
  56. return (NOW);
  57. }
  58. class TSIGTest : public ::testing::Test {
  59. protected:
  60. TSIGTest() :
  61. tsig_ctx(NULL), qid(0x2d65), test_name("www.example.com"),
  62. badkey_name("badkey.example.com"), test_class(RRClass::IN()),
  63. test_ttl(86400), message(Message::RENDER), buffer(0), renderer(buffer),
  64. dummy_data(1024, 0xdd), // should be sufficiently large for all tests
  65. dummy_record(badkey_name, any::TSIG(TSIGKey::HMACMD5_NAME(),
  66. 0x4da8877a,
  67. TSIGContext::DEFAULT_FUDGE,
  68. 0, NULL, qid, 0, 0, NULL))
  69. {
  70. // Make sure we use the system time by default so that we won't be
  71. // confused due to other tests that tweak the time.
  72. isc::util::detail::gettimeFunction = NULL;
  73. decodeBase64("SFuWd/q99SzF8Yzd1QbB9g==", secret);
  74. tsig_ctx.reset(new TSIGContext(TSIGKey(test_name,
  75. TSIGKey::HMACMD5_NAME(),
  76. &secret[0], secret.size())));
  77. tsig_verify_ctx.reset(new TSIGContext(TSIGKey(test_name,
  78. TSIGKey::HMACMD5_NAME(),
  79. &secret[0],
  80. secret.size())));
  81. }
  82. ~TSIGTest() {
  83. isc::util::detail::gettimeFunction = NULL;
  84. }
  85. // Many of the tests below create some DNS message and sign it under
  86. // some specific TSIG context. This helper method unifies the common
  87. // logic with slightly different parameters.
  88. ConstTSIGRecordPtr createMessageAndSign(uint16_t qid, const Name& qname,
  89. TSIGContext* ctx,
  90. unsigned int message_flags =
  91. RD_FLAG,
  92. RRType qtype = RRType::A(),
  93. const char* answer_data = NULL,
  94. const RRType* answer_type = NULL,
  95. bool add_question = true,
  96. Rcode rcode = Rcode::NOERROR());
  97. void createMessageFromFile(const char* datafile);
  98. // bit-wise constant flags to configure DNS header flags for test
  99. // messages.
  100. static const unsigned int QR_FLAG = 0x1;
  101. static const unsigned int AA_FLAG = 0x2;
  102. static const unsigned int RD_FLAG = 0x4;
  103. boost::scoped_ptr<TSIGContext> tsig_ctx;
  104. boost::scoped_ptr<TSIGContext> tsig_verify_ctx;
  105. TSIGKeyRing keyring;
  106. const uint16_t qid;
  107. const Name test_name;
  108. const Name badkey_name;
  109. const RRClass test_class;
  110. const RRTTL test_ttl;
  111. Message message;
  112. OutputBuffer buffer;
  113. MessageRenderer renderer;
  114. vector<uint8_t> secret;
  115. vector<uint8_t> dummy_data;
  116. const TSIGRecord dummy_record;
  117. vector<uint8_t> received_data;
  118. };
  119. ConstTSIGRecordPtr
  120. TSIGTest::createMessageAndSign(uint16_t id, const Name& qname,
  121. TSIGContext* ctx, unsigned int message_flags,
  122. RRType qtype, const char* answer_data,
  123. const RRType* answer_type, bool add_question,
  124. Rcode rcode)
  125. {
  126. message.clear(Message::RENDER);
  127. message.setQid(id);
  128. message.setOpcode(Opcode::QUERY());
  129. message.setRcode(rcode);
  130. if ((message_flags & QR_FLAG) != 0) {
  131. message.setHeaderFlag(Message::HEADERFLAG_QR);
  132. }
  133. if ((message_flags & AA_FLAG) != 0) {
  134. message.setHeaderFlag(Message::HEADERFLAG_AA);
  135. }
  136. if ((message_flags & RD_FLAG) != 0) {
  137. message.setHeaderFlag(Message::HEADERFLAG_RD);
  138. }
  139. if (add_question) {
  140. message.addQuestion(Question(qname, test_class, qtype));
  141. }
  142. if (answer_data != NULL) {
  143. if (answer_type == NULL) {
  144. answer_type = &qtype;
  145. }
  146. RRsetPtr answer_rrset(new RRset(qname, test_class, *answer_type,
  147. test_ttl));
  148. answer_rrset->addRdata(createRdata(*answer_type, test_class,
  149. answer_data));
  150. message.addRRset(Message::SECTION_ANSWER, answer_rrset);
  151. }
  152. renderer.clear();
  153. message.toWire(renderer);
  154. TSIGContext::State expected_new_state =
  155. (ctx->getState() == TSIGContext::INIT) ?
  156. TSIGContext::SENT_REQUEST : TSIGContext::SENT_RESPONSE;
  157. ConstTSIGRecordPtr tsig = ctx->sign(id, renderer.getData(),
  158. renderer.getLength());
  159. EXPECT_EQ(expected_new_state, ctx->getState());
  160. return (tsig);
  161. }
  162. void
  163. TSIGTest::createMessageFromFile(const char* datafile) {
  164. message.clear(Message::PARSE);
  165. received_data.clear();
  166. UnitTestUtil::readWireData(datafile, received_data);
  167. InputBuffer buffer(&received_data[0], received_data.size());
  168. message.fromWire(buffer);
  169. }
  170. void
  171. commonSignChecks(ConstTSIGRecordPtr tsig, uint16_t expected_qid,
  172. uint64_t expected_timesigned,
  173. const uint8_t* expected_mac, size_t expected_maclen,
  174. uint16_t expected_error = 0,
  175. uint16_t expected_otherlen = 0,
  176. const uint8_t* expected_otherdata = NULL,
  177. const Name& expected_algorithm = TSIGKey::HMACMD5_NAME())
  178. {
  179. ASSERT_TRUE(tsig != NULL);
  180. const any::TSIG& tsig_rdata = tsig->getRdata();
  181. EXPECT_EQ(expected_algorithm, tsig_rdata.getAlgorithm());
  182. EXPECT_EQ(expected_timesigned, tsig_rdata.getTimeSigned());
  183. EXPECT_EQ(300, tsig_rdata.getFudge());
  184. EXPECT_EQ(expected_maclen, tsig_rdata.getMACSize());
  185. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  186. tsig_rdata.getMAC(), tsig_rdata.getMACSize(),
  187. expected_mac, expected_maclen);
  188. EXPECT_EQ(expected_qid, tsig_rdata.getOriginalID());
  189. EXPECT_EQ(expected_error, tsig_rdata.getError());
  190. EXPECT_EQ(expected_otherlen, tsig_rdata.getOtherLen());
  191. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  192. tsig_rdata.getOtherData(), tsig_rdata.getOtherLen(),
  193. expected_otherdata, expected_otherlen);
  194. }
  195. void
  196. commonVerifyChecks(TSIGContext& ctx, const TSIGRecord* record,
  197. const void* data, size_t data_len, TSIGError expected_error,
  198. TSIGContext::State expected_new_state =
  199. TSIGContext::VERIFIED_RESPONSE)
  200. {
  201. EXPECT_EQ(expected_error, ctx.verify(record, data, data_len));
  202. EXPECT_EQ(expected_error, ctx.getError());
  203. EXPECT_EQ(expected_new_state, ctx.getState());
  204. }
  205. TEST_F(TSIGTest, initialState) {
  206. // Until signing or verifying, the state should be INIT
  207. EXPECT_EQ(TSIGContext::INIT, tsig_ctx->getState());
  208. // And there should be no error code.
  209. EXPECT_EQ(TSIGError(Rcode::NOERROR()), tsig_ctx->getError());
  210. }
  211. TEST_F(TSIGTest, constructFromKeyRing) {
  212. // Construct a TSIG context with an empty key ring. Key shouldn't be
  213. // found, and the BAD_KEY error should be recorded.
  214. TSIGContext ctx1(test_name, TSIGKey::HMACMD5_NAME(), keyring);
  215. EXPECT_EQ(TSIGContext::INIT, ctx1.getState());
  216. EXPECT_EQ(TSIGError::BAD_KEY(), ctx1.getError());
  217. // Add a matching key (we don't use the secret so leave it empty), and
  218. // construct it again. This time it should be constructed with a valid
  219. // key.
  220. keyring.add(TSIGKey(test_name, TSIGKey::HMACMD5_NAME(), NULL, 0));
  221. TSIGContext ctx2(test_name, TSIGKey::HMACMD5_NAME(), keyring);
  222. EXPECT_EQ(TSIGContext::INIT, ctx2.getState());
  223. EXPECT_EQ(TSIGError::NOERROR(), ctx2.getError());
  224. // Similar to the first case except that the key ring isn't empty but
  225. // it doesn't contain a matching key.
  226. TSIGContext ctx3(test_name, TSIGKey::HMACSHA1_NAME(), keyring);
  227. EXPECT_EQ(TSIGContext::INIT, ctx3.getState());
  228. EXPECT_EQ(TSIGError::BAD_KEY(), ctx3.getError());
  229. TSIGContext ctx4(Name("different-key.example"), TSIGKey::HMACMD5_NAME(),
  230. keyring);
  231. EXPECT_EQ(TSIGContext::INIT, ctx4.getState());
  232. EXPECT_EQ(TSIGError::BAD_KEY(), ctx4.getError());
  233. // "Unknown" algorithm name will result in BADKEY, too.
  234. TSIGContext ctx5(test_name, Name("unknown.algorithm"), keyring);
  235. EXPECT_EQ(TSIGContext::INIT, ctx5.getState());
  236. EXPECT_EQ(TSIGError::BAD_KEY(), ctx5.getError());
  237. }
  238. // Example output generated by
  239. // "dig -y www.example.com:SFuWd/q99SzF8Yzd1QbB9g== www.example.com
  240. // QID: 0x2d65
  241. // Time Signed: 0x00004da8877a
  242. // MAC: 227026ad297beee721ce6c6fff1e9ef3
  243. const uint8_t common_expected_mac[] = {
  244. 0x22, 0x70, 0x26, 0xad, 0x29, 0x7b, 0xee, 0xe7,
  245. 0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3
  246. };
  247. TEST_F(TSIGTest, sign) {
  248. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  249. {
  250. SCOPED_TRACE("Sign test for query");
  251. commonSignChecks(createMessageAndSign(qid, test_name, tsig_ctx.get()),
  252. qid, 0x4da8877a, common_expected_mac,
  253. sizeof(common_expected_mac));
  254. }
  255. }
  256. // Same test as sign, but specifying the key name with upper-case (i.e.
  257. // non canonical) characters. The digest must be the same. It should actually
  258. // be ensured at the level of TSIGKey, but we confirm that at this level, too.
  259. TEST_F(TSIGTest, signUsingUpperCasedKeyName) {
  260. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  261. TSIGContext cap_ctx(TSIGKey(Name("WWW.EXAMPLE.COM"),
  262. TSIGKey::HMACMD5_NAME(),
  263. &secret[0], secret.size()));
  264. {
  265. SCOPED_TRACE("Sign test for query using non canonical key name");
  266. commonSignChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid,
  267. 0x4da8877a, common_expected_mac,
  268. sizeof(common_expected_mac));
  269. }
  270. }
  271. // Same as the previous test, but for the algorithm name.
  272. TEST_F(TSIGTest, signUsingUpperCasedAlgorithmName) {
  273. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  274. TSIGContext cap_ctx(TSIGKey(test_name,
  275. Name("HMAC-md5.SIG-alg.REG.int"),
  276. &secret[0], secret.size()));
  277. {
  278. SCOPED_TRACE("Sign test for query using non canonical algorithm name");
  279. commonSignChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid,
  280. 0x4da8877a, common_expected_mac,
  281. sizeof(common_expected_mac));
  282. }
  283. }
  284. TEST_F(TSIGTest, signAtActualTime) {
  285. // Sign the message using the actual time, and check the accuracy of it.
  286. // We cannot reasonably predict the expected MAC, so don't bother to
  287. // check it.
  288. const uint64_t now = static_cast<uint64_t>(time(NULL));
  289. {
  290. SCOPED_TRACE("Sign test for query at actual time");
  291. ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
  292. tsig_ctx.get());
  293. const any::TSIG& tsig_rdata = tsig->getRdata();
  294. // Check the resulted time signed is in the range of [now, now + 5]
  295. // (5 is an arbitrary choice). Note that due to the order of the call
  296. // to time() and sign(), time signed must not be smaller than the
  297. // current time.
  298. EXPECT_LE(now, tsig_rdata.getTimeSigned());
  299. EXPECT_GE(now + 5, tsig_rdata.getTimeSigned());
  300. }
  301. }
  302. TEST_F(TSIGTest, signBadData) {
  303. // some specific bad data should be rejected proactively.
  304. const unsigned char dummy_data = 0;
  305. EXPECT_THROW(tsig_ctx->sign(0, NULL, 10), InvalidParameter);
  306. EXPECT_THROW(tsig_ctx->sign(0, &dummy_data, 0), InvalidParameter);
  307. }
  308. TEST_F(TSIGTest, verifyBadData) {
  309. // the data must at least hold the DNS message header and the specified
  310. // TSIG.
  311. EXPECT_THROW(tsig_ctx->verify(&dummy_record, &dummy_data[0],
  312. 12 + dummy_record.getLength() - 1),
  313. InvalidParameter);
  314. // And the data must not be NULL.
  315. EXPECT_THROW(tsig_ctx->verify(&dummy_record, NULL,
  316. 12 + dummy_record.getLength()),
  317. InvalidParameter);
  318. }
  319. #ifdef ENABLE_CUSTOM_OPERATOR_NEW
  320. // We enable this test only when we enable custom new/delete at build time
  321. // We could enable/disable the test runtime using the gtest filter, but
  322. // we'd basically like to minimize the number of disabled tests (they
  323. // should generally be considered tests that temporarily fail and should
  324. // be fixed).
  325. TEST_F(TSIGTest, signExceptionSafety) {
  326. // Check sign() provides the strong exception guarantee for the simpler
  327. // case (with a key error and empty MAC). The general case is more
  328. // complicated and involves more memory allocation, so the test result
  329. // won't be reliable.
  330. commonVerifyChecks(*tsig_verify_ctx, &dummy_record, &dummy_data[0],
  331. dummy_data.size(), TSIGError::BAD_KEY(),
  332. TSIGContext::RECEIVED_REQUEST);
  333. try {
  334. int dummydata;
  335. isc::util::unittests::force_throw_on_new = true;
  336. isc::util::unittests::throw_size_on_new = sizeof(TSIGRecord);
  337. tsig_verify_ctx->sign(0, &dummydata, sizeof(dummydata));
  338. isc::util::unittests::force_throw_on_new = false;
  339. ASSERT_FALSE(true) << "Expected throw on new, but it didn't happen";
  340. } catch (const std::bad_alloc&) {
  341. isc::util::unittests::force_throw_on_new = false;
  342. // sign() threw, so the state should still be RECEIVED_REQUEST
  343. EXPECT_EQ(TSIGContext::RECEIVED_REQUEST, tsig_verify_ctx->getState());
  344. }
  345. isc::util::unittests::force_throw_on_new = false;
  346. }
  347. #endif // ENABLE_CUSTOM_OPERATOR_NEW
  348. // Same test as "sign" but use a different algorithm just to confirm we don't
  349. // naively hardcode constants specific to a particular algorithm.
  350. // Test data generated by
  351. // "dig -y hmac-sha1:www.example.com:MA+QDhXbyqUak+qnMFyTyEirzng= www.example.com"
  352. // QID: 0x0967, RDflag
  353. // Current Time: 00004da8be86
  354. // Time Signed: 00004dae7d5f
  355. // HMAC Size: 20
  356. // HMAC: 415340c7daf824ed684ee586f7b5a67a2febc0d3
  357. TEST_F(TSIGTest, signUsingHMACSHA1) {
  358. isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>;
  359. secret.clear();
  360. decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret);
  361. TSIGContext sha1_ctx(TSIGKey(test_name, TSIGKey::HMACSHA1_NAME(),
  362. &secret[0], secret.size()));
  363. const uint16_t sha1_qid = 0x0967;
  364. const uint8_t expected_mac[] = {
  365. 0x41, 0x53, 0x40, 0xc7, 0xda, 0xf8, 0x24, 0xed, 0x68, 0x4e,
  366. 0xe5, 0x86, 0xf7, 0xb5, 0xa6, 0x7a, 0x2f, 0xeb, 0xc0, 0xd3
  367. };
  368. {
  369. SCOPED_TRACE("Sign test using HMAC-SHA1");
  370. commonSignChecks(createMessageAndSign(sha1_qid, test_name, &sha1_ctx),
  371. sha1_qid, 0x4dae7d5f, expected_mac,
  372. sizeof(expected_mac), 0, 0, NULL,
  373. TSIGKey::HMACSHA1_NAME());
  374. }
  375. }
  376. TEST_F(TSIGTest, signUsingHMACSHA224) {
  377. isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>;
  378. secret.clear();
  379. decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret);
  380. TSIGContext sha1_ctx(TSIGKey(test_name, TSIGKey::HMACSHA224_NAME(),
  381. &secret[0], secret.size()));
  382. const uint16_t sha1_qid = 0x0967;
  383. const uint8_t expected_mac[] = {
  384. 0x3b, 0x93, 0xd3, 0xc5, 0xf9, 0x64, 0xb9, 0xc5, 0x00, 0x35,
  385. 0x02, 0x69, 0x9f, 0xfc, 0x44, 0xd6, 0xe2, 0x66, 0xf4, 0x08,
  386. 0xef, 0x33, 0xa2, 0xda, 0xa1, 0x48, 0x71, 0xd3
  387. };
  388. {
  389. SCOPED_TRACE("Sign test using HMAC-SHA1");
  390. commonSignChecks(createMessageAndSign(sha1_qid, test_name, &sha1_ctx),
  391. sha1_qid, 0x4dae7d5f, expected_mac,
  392. sizeof(expected_mac), 0, 0, NULL,
  393. TSIGKey::HMACSHA224_NAME());
  394. }
  395. }
  396. // The first part of this test checks verifying the signed query used for
  397. // the "sign" test.
  398. // The second part of this test generates a signed response to the signed
  399. // query as follows:
  400. // Answer: www.example.com. 86400 IN A 192.0.2.1
  401. // MAC: 8fcda66a7cd1a3b9948eb1869d384a9f
  402. TEST_F(TSIGTest, verifyThenSignResponse) {
  403. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  404. // This test data for the message test has the same wire format data
  405. // as the message used in the "sign" test.
  406. createMessageFromFile("message_toWire2.wire");
  407. {
  408. SCOPED_TRACE("Verify test for request");
  409. commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
  410. &received_data[0], received_data.size(),
  411. TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST);
  412. }
  413. // Transform the original message to a response, then sign the response
  414. // with the context of "verified state".
  415. ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
  416. tsig_verify_ctx.get(),
  417. QR_FLAG|AA_FLAG|RD_FLAG,
  418. RRType::A(), "192.0.2.1");
  419. const uint8_t expected_mac[] = {
  420. 0x8f, 0xcd, 0xa6, 0x6a, 0x7c, 0xd1, 0xa3, 0xb9,
  421. 0x94, 0x8e, 0xb1, 0x86, 0x9d, 0x38, 0x4a, 0x9f
  422. };
  423. {
  424. SCOPED_TRACE("Sign test for response");
  425. commonSignChecks(tsig, qid, 0x4da8877a, expected_mac,
  426. sizeof(expected_mac));
  427. }
  428. }
  429. TEST_F(TSIGTest, verifyUpperCaseNames) {
  430. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  431. // This test data for the message test has the same wire format data
  432. // as the message used in the "sign" test.
  433. createMessageFromFile("tsig_verify9.wire");
  434. {
  435. SCOPED_TRACE("Verify test for request");
  436. commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
  437. &received_data[0], received_data.size(),
  438. TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST);
  439. }
  440. }
  441. TEST_F(TSIGTest, verifyForwardedMessage) {
  442. // Similar to the first part of the previous test, but this test emulates
  443. // the "forward" case, where the ID of the Header and the original ID in
  444. // TSIG is different.
  445. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  446. createMessageFromFile("tsig_verify6.wire");
  447. {
  448. SCOPED_TRACE("Verify test for forwarded request");
  449. commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
  450. &received_data[0], received_data.size(),
  451. TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST);
  452. }
  453. }
  454. // Example of signing multiple messages in a single TCP stream,
  455. // taken from data using BIND 9's "one-answer" transfer-format.
  456. // Request:
  457. // QID: 0x3410, flags (none)
  458. // Question: example.com/IN/AXFR
  459. // Time Signed: 0x4da8e951
  460. // MAC: 35b2fd08268781634400c7c8a5533b13
  461. // First message:
  462. // QID: 0x3410, flags QR, AA
  463. // Question: example.com/IN/AXFR
  464. // Answer: example.com. 86400 IN SOA ns.example.com. root.example.com. (
  465. // 2011041503 7200 3600 2592000 1200)
  466. // MAC: bdd612cd2c7f9e0648bd6dc23713e83c
  467. // Second message:
  468. // Answer: example.com. 86400 IN NS ns.example.com.
  469. // MAC: 102458f7f62ddd7d638d746034130968
  470. TEST_F(TSIGTest, signContinuation) {
  471. isc::util::detail::gettimeFunction = testGetTime<0x4da8e951>;
  472. const uint16_t axfr_qid = 0x3410;
  473. const Name zone_name("example.com");
  474. // Create and sign the AXFR request
  475. ConstTSIGRecordPtr tsig = createMessageAndSign(axfr_qid, zone_name,
  476. tsig_ctx.get(), 0,
  477. RRType::AXFR());
  478. // Then verify it (the wire format test data should contain the same
  479. // message data, and verification should succeed).
  480. received_data.clear();
  481. UnitTestUtil::readWireData("tsig_verify1.wire", received_data);
  482. {
  483. SCOPED_TRACE("Verify AXFR query");
  484. commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &received_data[0],
  485. received_data.size(), TSIGError::NOERROR(),
  486. TSIGContext::RECEIVED_REQUEST);
  487. }
  488. // Create and sign the first response message
  489. tsig = createMessageAndSign(axfr_qid, zone_name, tsig_verify_ctx.get(),
  490. AA_FLAG|QR_FLAG, RRType::AXFR(),
  491. "ns.example.com. root.example.com. "
  492. "2011041503 7200 3600 2592000 1200",
  493. &RRType::SOA());
  494. // Then verify it at the requester side.
  495. received_data.clear();
  496. UnitTestUtil::readWireData("tsig_verify2.wire", received_data);
  497. {
  498. SCOPED_TRACE("Verify first AXFR response");
  499. commonVerifyChecks(*tsig_ctx, tsig.get(), &received_data[0],
  500. received_data.size(), TSIGError::NOERROR());
  501. }
  502. // Create and sign the second response message
  503. const uint8_t expected_mac[] = {
  504. 0x10, 0x24, 0x58, 0xf7, 0xf6, 0x2d, 0xdd, 0x7d,
  505. 0x63, 0x8d, 0x74, 0x60, 0x34, 0x13, 0x09, 0x68
  506. };
  507. {
  508. SCOPED_TRACE("Sign test for continued response in TCP stream");
  509. tsig = createMessageAndSign(axfr_qid, zone_name, tsig_verify_ctx.get(),
  510. AA_FLAG|QR_FLAG, RRType::AXFR(),
  511. "ns.example.com.", &RRType::NS(), false);
  512. commonSignChecks(tsig, axfr_qid, 0x4da8e951, expected_mac,
  513. sizeof(expected_mac));
  514. }
  515. // Then verify it at the requester side.
  516. received_data.clear();
  517. UnitTestUtil::readWireData("tsig_verify3.wire", received_data);
  518. {
  519. SCOPED_TRACE("Verify second AXFR response");
  520. commonVerifyChecks(*tsig_ctx, tsig.get(), &received_data[0],
  521. received_data.size(), TSIGError::NOERROR());
  522. }
  523. }
  524. // BADTIME example, taken from data using specially hacked BIND 9's nsupdate
  525. // Query:
  526. // QID: 0x1830, RD flag
  527. // Current Time: 00004da8be86
  528. // Time Signed: 00004da8b9d6
  529. // Question: www.example.com/IN/SOA
  530. //(mac) 8406 7d50 b8e7 d054 3d50 5bd9 de2a bb68
  531. // Response:
  532. // QRbit, RCODE=9(NOTAUTH)
  533. // Time Signed: 00004da8b9d6 (the one in the query)
  534. // MAC: d4b043f6f44495ec8a01260e39159d76
  535. // Error: 0x12 (BADTIME), Other Len: 6
  536. // Other data: 00004da8be86
  537. TEST_F(TSIGTest, badtimeResponse) {
  538. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
  539. const uint16_t test_qid = 0x7fc4;
  540. ConstTSIGRecordPtr tsig = createMessageAndSign(test_qid, test_name,
  541. tsig_ctx.get(), 0,
  542. RRType::SOA());
  543. // "advance the clock" and try validating, which should fail due to BADTIME
  544. isc::util::detail::gettimeFunction = testGetTime<0x4da8be86>;
  545. {
  546. SCOPED_TRACE("Verify resulting in BADTIME due to expired SIG");
  547. commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &dummy_data[0],
  548. dummy_data.size(), TSIGError::BAD_TIME(),
  549. TSIGContext::RECEIVED_REQUEST);
  550. }
  551. // make and sign a response in the context of TSIG error.
  552. tsig = createMessageAndSign(test_qid, test_name, tsig_verify_ctx.get(),
  553. QR_FLAG, RRType::SOA(), NULL, NULL,
  554. true, Rcode::NOTAUTH());
  555. const uint8_t expected_otherdata[] = { 0, 0, 0x4d, 0xa8, 0xbe, 0x86 };
  556. const uint8_t expected_mac[] = {
  557. 0xd4, 0xb0, 0x43, 0xf6, 0xf4, 0x44, 0x95, 0xec,
  558. 0x8a, 0x01, 0x26, 0x0e, 0x39, 0x15, 0x9d, 0x76
  559. };
  560. {
  561. SCOPED_TRACE("Sign test for response with BADTIME");
  562. commonSignChecks(tsig, message.getQid(), 0x4da8b9d6,
  563. expected_mac, sizeof(expected_mac),
  564. 18, // error: BADTIME
  565. sizeof(expected_otherdata),
  566. expected_otherdata);
  567. }
  568. }
  569. TEST_F(TSIGTest, badtimeResponse2) {
  570. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
  571. ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
  572. tsig_ctx.get(), 0,
  573. RRType::SOA());
  574. // "rewind the clock" and try validating, which should fail due to BADTIME
  575. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 600>;
  576. {
  577. SCOPED_TRACE("Verify resulting in BADTIME due to too future SIG");
  578. commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &dummy_data[0],
  579. dummy_data.size(), TSIGError::BAD_TIME(),
  580. TSIGContext::RECEIVED_REQUEST);
  581. }
  582. }
  583. TEST_F(TSIGTest, badtimeBoundaries) {
  584. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
  585. // Test various boundary conditions. We intentionally use the magic
  586. // number of 300 instead of the constant variable for testing.
  587. // In the okay cases, signature is not correct, but it's sufficient to
  588. // check the error code isn't BADTIME for the purpose of this test.
  589. ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
  590. tsig_ctx.get(), 0,
  591. RRType::SOA());
  592. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 + 301>;
  593. EXPECT_EQ(TSIGError::BAD_TIME(),
  594. tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
  595. dummy_data.size()));
  596. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 + 300>;
  597. EXPECT_NE(TSIGError::BAD_TIME(),
  598. tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
  599. dummy_data.size()));
  600. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 301>;
  601. EXPECT_EQ(TSIGError::BAD_TIME(),
  602. tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
  603. dummy_data.size()));
  604. isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 300>;
  605. EXPECT_NE(TSIGError::BAD_TIME(),
  606. tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
  607. dummy_data.size()));
  608. }
  609. TEST_F(TSIGTest, badtimeOverflow) {
  610. isc::util::detail::gettimeFunction = testGetTime<200>;
  611. ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
  612. tsig_ctx.get(), 0,
  613. RRType::SOA());
  614. // This should be in the okay range, but since "200 - fudge" overflows
  615. // and we compare them as 64-bit unsigned integers, it results in a false
  616. // positive (we intentionally accept that).
  617. isc::util::detail::gettimeFunction = testGetTime<100>;
  618. EXPECT_EQ(TSIGError::BAD_TIME(),
  619. tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
  620. dummy_data.size()));
  621. }
  622. TEST_F(TSIGTest, badsigResponse) {
  623. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  624. // Try to sign a simple message with bogus secret. It should fail
  625. // with BADSIG.
  626. createMessageFromFile("message_toWire2.wire");
  627. TSIGContext bad_ctx(TSIGKey(test_name, TSIGKey::HMACMD5_NAME(),
  628. &dummy_data[0], dummy_data.size()));
  629. {
  630. SCOPED_TRACE("Verify resulting in BADSIG");
  631. commonVerifyChecks(bad_ctx, message.getTSIGRecord(),
  632. &received_data[0], received_data.size(),
  633. TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST);
  634. }
  635. // Sign the same message (which doesn't matter for this test) with the
  636. // context of "checked state".
  637. {
  638. SCOPED_TRACE("Sign test for response with BADSIG error");
  639. commonSignChecks(createMessageAndSign(qid, test_name, &bad_ctx),
  640. message.getQid(), 0x4da8877a, NULL, 0,
  641. 16); // 16: BADSIG
  642. }
  643. }
  644. TEST_F(TSIGTest, badkeyResponse) {
  645. // A similar test as badsigResponse but for BADKEY
  646. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  647. tsig_ctx.reset(new TSIGContext(badkey_name, TSIGKey::HMACMD5_NAME(),
  648. keyring));
  649. {
  650. SCOPED_TRACE("Verify resulting in BADKEY");
  651. commonVerifyChecks(*tsig_ctx, &dummy_record, &dummy_data[0],
  652. dummy_data.size(), TSIGError::BAD_KEY(),
  653. TSIGContext::RECEIVED_REQUEST);
  654. }
  655. {
  656. SCOPED_TRACE("Sign test for response with BADKEY error");
  657. ConstTSIGRecordPtr sig = createMessageAndSign(qid, test_name,
  658. tsig_ctx.get());
  659. EXPECT_EQ(badkey_name, sig->getName());
  660. commonSignChecks(sig, qid, 0x4da8877a, NULL, 0, 17); // 17: BADKEY
  661. }
  662. }
  663. TEST_F(TSIGTest, badkeyForResponse) {
  664. // "BADKEY" case for a response to a signed message
  665. createMessageAndSign(qid, test_name, tsig_ctx.get());
  666. {
  667. SCOPED_TRACE("Verify a response resulting in BADKEY");
  668. commonVerifyChecks(*tsig_ctx, &dummy_record, &dummy_data[0],
  669. dummy_data.size(), TSIGError::BAD_KEY(),
  670. TSIGContext::SENT_REQUEST);
  671. }
  672. // A similar case with a different algorithm
  673. const TSIGRecord dummy_record2(test_name,
  674. any::TSIG(TSIGKey::HMACSHA1_NAME(),
  675. 0x4da8877a,
  676. TSIGContext::DEFAULT_FUDGE,
  677. 0, NULL, qid, 0, 0, NULL));
  678. {
  679. SCOPED_TRACE("Verify a response resulting in BADKEY due to bad alg");
  680. commonVerifyChecks(*tsig_ctx, &dummy_record2, &dummy_data[0],
  681. dummy_data.size(), TSIGError::BAD_KEY(),
  682. TSIGContext::SENT_REQUEST);
  683. }
  684. }
  685. TEST_F(TSIGTest, badsigThenValidate) {
  686. // According to RFC2845 4.6, if TSIG verification fails the client
  687. // should discard that message and wait for another signed response.
  688. // This test emulates that situation.
  689. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  690. createMessageAndSign(qid, test_name, tsig_ctx.get());
  691. createMessageFromFile("tsig_verify4.wire");
  692. {
  693. SCOPED_TRACE("Verify a response that should fail due to BADSIG");
  694. commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
  695. &received_data[0], received_data.size(),
  696. TSIGError::BAD_SIG(), TSIGContext::SENT_REQUEST);
  697. }
  698. createMessageFromFile("tsig_verify5.wire");
  699. {
  700. SCOPED_TRACE("Verify a response after a BADSIG failure");
  701. commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
  702. &received_data[0], received_data.size(),
  703. TSIGError::NOERROR(),
  704. TSIGContext::VERIFIED_RESPONSE);
  705. }
  706. }
  707. TEST_F(TSIGTest, nosigThenValidate) {
  708. // Similar to the previous test, but the first response doesn't contain
  709. // TSIG.
  710. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  711. createMessageAndSign(qid, test_name, tsig_ctx.get());
  712. {
  713. SCOPED_TRACE("Verify a response without TSIG that should exist");
  714. commonVerifyChecks(*tsig_ctx, NULL, &dummy_data[0],
  715. dummy_data.size(), TSIGError::FORMERR(),
  716. TSIGContext::SENT_REQUEST);
  717. }
  718. createMessageFromFile("tsig_verify5.wire");
  719. {
  720. SCOPED_TRACE("Verify a response after a FORMERR failure");
  721. commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
  722. &received_data[0], received_data.size(),
  723. TSIGError::NOERROR(),
  724. TSIGContext::VERIFIED_RESPONSE);
  725. }
  726. }
  727. TEST_F(TSIGTest, badtimeThenValidate) {
  728. // Similar to the previous test, but the first response results in BADTIME.
  729. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  730. ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
  731. tsig_ctx.get());
  732. // "advance the clock" and try validating, which should fail due to BADTIME
  733. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a + 600>;
  734. {
  735. SCOPED_TRACE("Verify resulting in BADTIME due to expired SIG");
  736. commonVerifyChecks(*tsig_ctx, tsig.get(), &dummy_data[0],
  737. dummy_data.size(), TSIGError::BAD_TIME(),
  738. TSIGContext::SENT_REQUEST);
  739. }
  740. // revert the clock again.
  741. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  742. createMessageFromFile("tsig_verify5.wire");
  743. {
  744. SCOPED_TRACE("Verify a response after a BADTIME failure");
  745. commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
  746. &received_data[0], received_data.size(),
  747. TSIGError::NOERROR(),
  748. TSIGContext::VERIFIED_RESPONSE);
  749. }
  750. }
  751. TEST_F(TSIGTest, emptyMAC) {
  752. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  753. // We don't allow empty MAC unless the TSIG error is BADSIG or BADKEY.
  754. createMessageFromFile("tsig_verify7.wire");
  755. {
  756. SCOPED_TRACE("Verify test for request");
  757. commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
  758. &received_data[0], received_data.size(),
  759. TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST);
  760. }
  761. // If the empty MAC comes with a BADKEY error, the error is passed
  762. // transparently.
  763. createMessageFromFile("tsig_verify8.wire");
  764. {
  765. SCOPED_TRACE("Verify test for request");
  766. commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
  767. &received_data[0], received_data.size(),
  768. TSIGError::BAD_KEY(), TSIGContext::RECEIVED_REQUEST);
  769. }
  770. }
  771. TEST_F(TSIGTest, verifyAfterSendResponse) {
  772. // Once the context is used for sending a signed response, it shouldn't
  773. // be used for further verification.
  774. // The following are essentially the same as what verifyThenSignResponse
  775. // does with simplification.
  776. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  777. createMessageFromFile("message_toWire2.wire");
  778. tsig_verify_ctx->verify(message.getTSIGRecord(), &received_data[0],
  779. received_data.size());
  780. EXPECT_EQ(TSIGContext::RECEIVED_REQUEST, tsig_verify_ctx->getState());
  781. createMessageAndSign(qid, test_name, tsig_verify_ctx.get(),
  782. QR_FLAG|AA_FLAG|RD_FLAG, RRType::A(), "192.0.2.1");
  783. EXPECT_EQ(TSIGContext::SENT_RESPONSE, tsig_verify_ctx->getState());
  784. // Now trying further verification.
  785. createMessageFromFile("message_toWire2.wire");
  786. EXPECT_THROW(tsig_verify_ctx->verify(message.getTSIGRecord(),
  787. &received_data[0],
  788. received_data.size()),
  789. TSIGContextError);
  790. }
  791. TEST_F(TSIGTest, signAfterVerified) {
  792. // Likewise, once the context verifies a response, it shouldn't for
  793. // signing any more.
  794. // The following are borrowed from badsigThenValidate (without the
  795. // intermediate failure)
  796. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  797. createMessageAndSign(qid, test_name, tsig_ctx.get());
  798. createMessageFromFile("tsig_verify5.wire");
  799. tsig_ctx->verify(message.getTSIGRecord(), &received_data[0],
  800. received_data.size());
  801. EXPECT_EQ(TSIGContext::VERIFIED_RESPONSE, tsig_ctx->getState());
  802. // Now trying further signing.
  803. EXPECT_THROW(createMessageAndSign(qid, test_name, tsig_ctx.get()),
  804. TSIGContextError);
  805. }
  806. TEST_F(TSIGTest, tooShortMAC) {
  807. // Too short MAC should be rejected.
  808. // Note: when we implement RFC4635-based checks, the error code will
  809. // (probably) be FORMERR.
  810. isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
  811. createMessageFromFile("tsig_verify10.wire");
  812. {
  813. SCOPED_TRACE("Verify test for request");
  814. commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
  815. &received_data[0], received_data.size(),
  816. TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST);
  817. }
  818. }
  819. } // end namespace