1 // Copyright (C) 2010-2019 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 #include <config.h>
8
9 #include <string>
10
11 #include <exceptions/exceptions.h>
12
13 #include <util/buffer.h>
14 #include <dns/exceptions.h>
15 #include <dns/messagerenderer.h>
16 #include <dns/rdata.h>
17 #include <dns/rdataclass.h>
18 #include <dns/rrclass.h>
19 #include <dns/rrtype.h>
20 #include <dns/tsigerror.h>
21
22 #include <gtest/gtest.h>
23
24 #include <dns/tests/unittest_util.h>
25 #include <dns/tests/rdata_unittest.h>
26 #include <util/unittests/wiredata.h>
27
28 using namespace std;
29 using namespace isc;
30 using namespace isc::dns;
31 using namespace isc::util;
32 using namespace isc::dns::rdata;
33 using isc::UnitTestUtil;
34 using isc::util::unittests::matchWireData;
35
36 namespace {
37
38 class Rdata_TSIG_Test : public RdataTest {
39 protected:
Rdata_TSIG_Test()40 Rdata_TSIG_Test() :
41 // no MAC or Other Data
42 valid_text1("hmac-md5.sig-alg.reg.int. 1286779327 300 "
43 "0 16020 BADKEY 0"),
44 // MAC but no Other Data
45 valid_text2("hmac-sha256. 1286779327 300 12 "
46 "FAKEFAKEFAKEFAKE 16020 BADSIG 0"),
47 // MAC and Other Data
48 valid_text3("hmac-sha1. 1286779327 300 12 "
49 "FAKEFAKEFAKEFAKE 16020 BADTIME 6 FAKEFAKE"),
50 // MAC and Other Data (with Error that doesn't expect Other Data)
51 valid_text4("hmac-sha1. 1286779327 300 12 "
52 "FAKEFAKEFAKEFAKE 16020 BADSIG 6 FAKEFAKE"),
53 // numeric error code
54 valid_text5("hmac-sha256. 1286779327 300 12 "
55 "FAKEFAKEFAKEFAKE 16020 2845 0"),
56 rdata_tsig(valid_text1)
57 {}
58
checkFromText_None(const string & rdata_str)59 void checkFromText_None(const string& rdata_str) {
60 checkFromText<any::TSIG, isc::Exception, isc::Exception>(
61 rdata_str, rdata_tsig, false, false);
62 }
63
checkFromText_InvalidText(const string & rdata_str)64 void checkFromText_InvalidText(const string& rdata_str) {
65 checkFromText<any::TSIG, InvalidRdataText, InvalidRdataText>(
66 rdata_str, rdata_tsig, true, true);
67 }
68
checkFromText_BadValue(const string & rdata_str)69 void checkFromText_BadValue(const string& rdata_str) {
70 checkFromText<any::TSIG, BadValue, BadValue>(
71 rdata_str, rdata_tsig, true, true);
72 }
73
checkFromText_LexerError(const string & rdata_str)74 void checkFromText_LexerError(const string& rdata_str) {
75 checkFromText
76 <any::TSIG, InvalidRdataText, MasterLexer::LexerError>(
77 rdata_str, rdata_tsig, true, true);
78 }
79
checkFromText_TooLongLabel(const string & rdata_str)80 void checkFromText_TooLongLabel(const string& rdata_str) {
81 checkFromText<any::TSIG, TooLongLabel, TooLongLabel>(
82 rdata_str, rdata_tsig, true, true);
83 }
84
checkFromText_EmptyLabel(const string & rdata_str)85 void checkFromText_EmptyLabel(const string& rdata_str) {
86 checkFromText<any::TSIG, EmptyLabel, EmptyLabel>(
87 rdata_str, rdata_tsig, true, true);
88 }
89
checkFromText_BadString(const string & rdata_str)90 void checkFromText_BadString(const string& rdata_str) {
91 checkFromText
92 <any::TSIG, InvalidRdataText, isc::Exception>(
93 rdata_str, rdata_tsig, true, false);
94 }
95
96 template <typename Output>
97 void toWireCommonChecks(Output& output) const;
98
99 const string valid_text1;
100 const string valid_text2;
101 const string valid_text3;
102 const string valid_text4;
103 const string valid_text5;
104 vector<uint8_t> expect_data;
105 const any::TSIG rdata_tsig; // commonly used test RDATA
106 };
107
TEST_F(Rdata_TSIG_Test,fromText)108 TEST_F(Rdata_TSIG_Test, fromText) {
109 // normal case. it also tests getter methods.
110 EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), rdata_tsig.getAlgorithm());
111 EXPECT_EQ(1286779327, rdata_tsig.getTimeSigned());
112 EXPECT_EQ(300, rdata_tsig.getFudge());
113 EXPECT_EQ(0, rdata_tsig.getMACSize());
114 EXPECT_EQ(static_cast<void*>(NULL), rdata_tsig.getMAC());
115 EXPECT_EQ(16020, rdata_tsig.getOriginalID());
116 EXPECT_EQ(TSIGError::BAD_KEY_CODE, rdata_tsig.getError());
117 EXPECT_EQ(0, rdata_tsig.getOtherLen());
118 EXPECT_EQ(static_cast<void*>(NULL), rdata_tsig.getOtherData());
119
120 any::TSIG tsig2(valid_text2);
121 EXPECT_EQ(12, tsig2.getMACSize());
122 EXPECT_EQ(TSIGError::BAD_SIG_CODE, tsig2.getError());
123
124 any::TSIG tsig3(valid_text3);
125 EXPECT_EQ(6, tsig3.getOtherLen());
126
127 // The other data is unusual, but we don't reject it.
128 EXPECT_NO_THROW(any::TSIG tsig4(valid_text4));
129
130 // numeric representation of TSIG error
131 any::TSIG tsig5(valid_text5);
132 EXPECT_EQ(2845, tsig5.getError());
133
134 // not fully qualified algorithm name
135 any::TSIG tsig1("hmac-md5.sig-alg.reg.int 1286779327 300 "
136 "0 16020 BADKEY 0");
137 EXPECT_EQ(0, tsig1.compare(rdata_tsig));
138
139 // multi-line rdata
140 checkFromText_None("hmac-md5.sig-alg.reg.int. ( 1286779327 300 \n"
141 "0 16020 BADKEY 0 )");
142
143 // short-form HMAC-MD5 name
144 const any::TSIG tsig6("hmac-md5. 1286779327 300 0 16020 BADKEY 0");
145 EXPECT_EQ(0, tsig6.compare(rdata_tsig));
146 };
147
TEST_F(Rdata_TSIG_Test,badText)148 TEST_F(Rdata_TSIG_Test, badText) {
149 // too many fields
150 checkFromText_BadString(valid_text1 + " 0 0");
151 // not enough fields
152 checkFromText_LexerError("foo 0 0 0 0 BADKEY");
153 // bad domain name
154 checkFromText_TooLongLabel(
155 "0123456789012345678901234567890123456789012345678901234567890123"
156 " 0 0 0 0 BADKEY 0");
157 checkFromText_EmptyLabel("foo..bar 0 0 0 0 BADKEY");
158 // time is too large (2814...6 is 2^48)
159 checkFromText_InvalidText("foo 281474976710656 0 0 0 BADKEY 0");
160 // invalid time (negative)
161 checkFromText_InvalidText("foo -1 0 0 0 BADKEY 0");
162 // invalid time (not a number)
163 checkFromText_InvalidText("foo TIME 0 0 0 BADKEY 0");
164 // fudge is too large
165 checkFromText_InvalidText("foo 0 65536 0 0 BADKEY 0");
166 // invalid fudge (negative)
167 checkFromText_LexerError("foo 0 -1 0 0 BADKEY 0");
168 // invalid fudge (not a number)
169 checkFromText_LexerError("foo 0 FUDGE 0 0 BADKEY 0");
170 // MAC size is too large
171 checkFromText_InvalidText("foo 0 0 65536 0 BADKEY 0");
172 // invalid MAC size (negative)
173 checkFromText_LexerError("foo 0 0 -1 0 BADKEY 0");
174 // invalid MAC size (not a number)
175 checkFromText_LexerError("foo 0 0 MACSIZE 0 BADKEY 0");
176 // MAC size and MAC mismatch
177 checkFromText_InvalidText("foo 0 0 9 FAKE 0 BADKEY 0");
178 // MAC is bad base64
179 checkFromText_BadValue("foo 0 0 3 FAK= 0 BADKEY 0");
180 // Unknown error code
181 checkFromText_InvalidText("foo 0 0 0 0 TEST 0");
182 // Numeric error code is too large
183 checkFromText_InvalidText("foo 0 0 0 0 65536 0");
184 // Numeric error code is negative
185 checkFromText_InvalidText("foo 0 0 0 0 -1 0");
186 // Other len is too large
187 checkFromText_InvalidText("foo 0 0 0 0 NOERROR 65536 FAKE");
188 // Other len is negative
189 checkFromText_LexerError("foo 0 0 0 0 NOERROR -1 FAKE");
190 // invalid Other len
191 checkFromText_LexerError("foo 0 0 0 0 NOERROR LEN FAKE");
192 // Other len and data mismatch
193 checkFromText_InvalidText("foo 0 0 0 0 NOERROR 9 FAKE");
194 }
195
196 void
fromWireCommonChecks(const any::TSIG & tsig)197 fromWireCommonChecks(const any::TSIG& tsig) {
198 EXPECT_EQ(Name("hmac-sha256"), tsig.getAlgorithm());
199 EXPECT_EQ(1286978795, tsig.getTimeSigned());
200 EXPECT_EQ(300, tsig.getFudge());
201
202 vector<uint8_t> expect_mac(32, 'x');
203 matchWireData(&expect_mac[0], expect_mac.size(),
204 tsig.getMAC(), tsig.getMACSize());
205
206 EXPECT_EQ(2845, tsig.getOriginalID());
207
208 EXPECT_EQ(0, tsig.getOtherLen());
209 EXPECT_EQ(static_cast<const void*>(NULL), tsig.getOtherData());
210 }
211
TEST_F(Rdata_TSIG_Test,createFromWire)212 TEST_F(Rdata_TSIG_Test, createFromWire) {
213 RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
214 "rdata_tsig_fromWire1.wire"));
215 fromWireCommonChecks(dynamic_cast<any::TSIG&>(*rdata));
216 }
217
TEST_F(Rdata_TSIG_Test,createFromWireWithOtherData)218 TEST_F(Rdata_TSIG_Test, createFromWireWithOtherData) {
219 RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
220 "rdata_tsig_fromWire2.wire"));
221 const any::TSIG& tsig(dynamic_cast<any::TSIG&>(*rdata));
222
223 EXPECT_EQ(18, tsig.getError());
224 const uint64_t otherdata = 1286978795 + 300 + 1; // time-signed + fudge + 1
225 expect_data.resize(6);
226 expect_data[0] = (otherdata >> 40);
227 expect_data[1] = ((otherdata >> 32) & 0xff);
228 expect_data[2] = ((otherdata >> 24) & 0xff);
229 expect_data[3] = ((otherdata >> 16) & 0xff);
230 expect_data[4] = ((otherdata >> 8) & 0xff);
231 expect_data[5] = (otherdata & 0xff);
232 matchWireData(&expect_data[0], expect_data.size(),
233 tsig.getOtherData(), tsig.getOtherLen());
234 }
235
TEST_F(Rdata_TSIG_Test,createFromWireWithoutMAC)236 TEST_F(Rdata_TSIG_Test, createFromWireWithoutMAC) {
237 RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
238 "rdata_tsig_fromWire3.wire"));
239 const any::TSIG& tsig(dynamic_cast<any::TSIG&>(*rdata));
240 EXPECT_EQ(16, tsig.getError());
241 EXPECT_EQ(0, tsig.getMACSize());
242 EXPECT_EQ(static_cast<const void*>(NULL), tsig.getMAC());
243 }
244
TEST_F(Rdata_TSIG_Test,createFromWireWithCompression)245 TEST_F(Rdata_TSIG_Test, createFromWireWithCompression) {
246 RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
247 "rdata_tsig_fromWire4.wire",
248 // we need to skip the dummy name:
249 Name("hmac-sha256").getLength()));
250 fromWireCommonChecks(dynamic_cast<any::TSIG&>(*rdata));
251 }
252
TEST_F(Rdata_TSIG_Test,badFromWire)253 TEST_F(Rdata_TSIG_Test, badFromWire) {
254 // RDLENGTH is too short:
255 EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
256 "rdata_tsig_fromWire5.wire"),
257 InvalidRdataLength);
258 // RDLENGTH is too long:
259 EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
260 "rdata_tsig_fromWire6.wire"),
261 InvalidRdataLength);
262 // Algorithm name is broken:
263 EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
264 "rdata_tsig_fromWire7.wire"),
265 DNSMessageFORMERR);
266 // MAC size is bogus:
267 EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
268 "rdata_tsig_fromWire8.wire"),
269 InvalidBufferPosition);
270 // Other-data length is bogus:
271 EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
272 "rdata_tsig_fromWire9.wire"),
273 InvalidBufferPosition);
274 }
275
TEST_F(Rdata_TSIG_Test,copyConstruct)276 TEST_F(Rdata_TSIG_Test, copyConstruct) {
277 const any::TSIG copy(rdata_tsig);
278 EXPECT_EQ(0, copy.compare(rdata_tsig));
279
280 // Check the copied data is valid even after the original is deleted
281 any::TSIG* copy2 = new any::TSIG(rdata_tsig);
282 any::TSIG copy3(*copy2);
283 delete copy2;
284 EXPECT_EQ(0, copy3.compare(rdata_tsig));
285 }
286
TEST_F(Rdata_TSIG_Test,createFromParams)287 TEST_F(Rdata_TSIG_Test, createFromParams) {
288 EXPECT_EQ(0, rdata_tsig.compare(any::TSIG(Name("hmac-md5.sig-alg.reg.int"),
289 1286779327, 300, 0, NULL, 16020,
290 17, 0, NULL)));
291
292 const uint8_t fake_data[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84,
293 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 };
294 EXPECT_EQ(0, any::TSIG(valid_text2).compare(
295 any::TSIG(Name("hmac-sha256"), 1286779327, 300, 12,
296 fake_data, 16020, 16, 0, NULL)));
297
298 const uint8_t fake_data2[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 };
299 EXPECT_EQ(0, any::TSIG(valid_text3).compare(
300 any::TSIG(Name("hmac-sha1"), 1286779327, 300, 12,
301 fake_data, 16020, 18, 6, fake_data2)));
302
303 EXPECT_THROW(any::TSIG(Name("hmac-sha256"), 1ULL << 48, 300, 12,
304 fake_data, 16020, 18, 6, fake_data2),
305 isc::OutOfRange);
306 EXPECT_THROW(any::TSIG(Name("hmac-sha256"), 0, 300, 0, fake_data, 16020,
307 18, 0, NULL),
308 isc::InvalidParameter);
309 EXPECT_THROW(any::TSIG(Name("hmac-sha256"), 0, 300, 12, NULL, 16020,
310 18, 0, NULL),
311 isc::InvalidParameter);
312 EXPECT_THROW(any::TSIG(Name("hmac-sha256"), 0, 300, 0, NULL, 16020,
313 18, 0, fake_data),
314 isc::InvalidParameter);
315 EXPECT_THROW(any::TSIG(Name("hmac-sha256"), 0, 300, 0, NULL, 16020,
316 18, 6, NULL),
317 isc::InvalidParameter);
318 }
319
TEST_F(Rdata_TSIG_Test,assignment)320 TEST_F(Rdata_TSIG_Test, assignment) {
321 any::TSIG copy(valid_text2);
322 copy = rdata_tsig;
323 EXPECT_EQ(0, copy.compare(rdata_tsig));
324
325 // Check if the copied data is valid even after the original is deleted
326 any::TSIG* copy2 = new any::TSIG(rdata_tsig);
327 any::TSIG copy3(valid_text2);
328 copy3 = *copy2;
329 delete copy2;
330 EXPECT_EQ(0, copy3.compare(rdata_tsig));
331
332 // Self assignment
333 copy = *©
334 EXPECT_EQ(0, copy.compare(rdata_tsig));
335 }
336
337 template <typename Output>
338 void
toWireCommonChecks(Output & output) const339 Rdata_TSIG_Test::toWireCommonChecks(Output& output) const {
340 vector<uint8_t> expect_data;
341
342 output.clear();
343 expect_data.clear();
344 rdata_tsig.toWire(output);
345 // read the expected wire format data and trim the RDLEN part.
346 UnitTestUtil::readWireData("rdata_tsig_toWire1.wire", expect_data);
347 expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
348 matchWireData(&expect_data[0], expect_data.size(),
349 output.getData(), output.getLength());
350
351 expect_data.clear();
352 output.clear();
353 any::TSIG(valid_text2).toWire(output);
354 UnitTestUtil::readWireData("rdata_tsig_toWire2.wire", expect_data);
355 expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
356 matchWireData(&expect_data[0], expect_data.size(),
357 output.getData(), output.getLength());
358
359 expect_data.clear();
360 output.clear();
361 any::TSIG(valid_text3).toWire(output);
362 UnitTestUtil::readWireData("rdata_tsig_toWire3.wire", expect_data);
363 expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
364 matchWireData(&expect_data[0], expect_data.size(),
365 output.getData(), output.getLength());
366 }
367
TEST_F(Rdata_TSIG_Test,toWireBuffer)368 TEST_F(Rdata_TSIG_Test, toWireBuffer) {
369 toWireCommonChecks<OutputBuffer>(obuffer);
370 }
371
TEST_F(Rdata_TSIG_Test,toWireRenderer)372 TEST_F(Rdata_TSIG_Test, toWireRenderer) {
373 toWireCommonChecks<MessageRenderer>(renderer);
374
375 // check algorithm name won't compressed when it would otherwise.
376 expect_data.clear();
377 renderer.clear();
378 renderer.writeName(Name("hmac-md5.sig-alg.reg.int"));
379 renderer.writeUint16(42); // RDLEN
380 rdata_tsig.toWire(renderer);
381 UnitTestUtil::readWireData("rdata_tsig_toWire4.wire", expect_data);
382 matchWireData(&expect_data[0], expect_data.size(),
383 renderer.getData(), renderer.getLength());
384
385 // check algorithm can be used as a compression target.
386 expect_data.clear();
387 renderer.clear();
388 renderer.writeUint16(42);
389 rdata_tsig.toWire(renderer);
390 renderer.writeName(Name("hmac-md5.sig-alg.reg.int"));
391 UnitTestUtil::readWireData("rdata_tsig_toWire5.wire", expect_data);
392 matchWireData(&expect_data[0], expect_data.size(),
393 renderer.getData(), renderer.getLength());
394 }
395
TEST_F(Rdata_TSIG_Test,toText)396 TEST_F(Rdata_TSIG_Test, toText) {
397 EXPECT_EQ(valid_text1, rdata_tsig.toText());
398 EXPECT_EQ(valid_text2, any::TSIG(valid_text2).toText());
399 EXPECT_EQ(valid_text3, any::TSIG(valid_text3).toText());
400 EXPECT_EQ(valid_text5, any::TSIG(valid_text5).toText());
401 }
402
TEST_F(Rdata_TSIG_Test,compare)403 TEST_F(Rdata_TSIG_Test, compare) {
404 // test RDATAs, sorted in the ascending order.
405 // "AAAA" encoded in BASE64 corresponds to 0x000000, so it should be the
406 // smallest data of the same length.
407 vector<any::TSIG> compare_set;
408 compare_set.push_back(any::TSIG("a.example 0 300 0 16020 0 0"));
409 compare_set.push_back(any::TSIG("example 0 300 0 16020 0 0"));
410 compare_set.push_back(any::TSIG("example 1 300 0 16020 0 0"));
411 compare_set.push_back(any::TSIG("example 1 600 0 16020 0 0"));
412 compare_set.push_back(any::TSIG("example 1 600 3 AAAA 16020 0 0"));
413 compare_set.push_back(any::TSIG("example 1 600 3 FAKE 16020 0 0"));
414 compare_set.push_back(any::TSIG("example 1 600 3 FAKE 16021 0 0"));
415 compare_set.push_back(any::TSIG("example 1 600 3 FAKE 16021 1 0"));
416 compare_set.push_back(any::TSIG("example 1 600 3 FAKE 16021 1 3 AAAA"));
417 compare_set.push_back(any::TSIG("example 1 600 3 FAKE 16021 1 3 FAKE"));
418
419 EXPECT_EQ(0, compare_set[0].compare(
420 any::TSIG("A.EXAMPLE 0 300 0 16020 0 0")));
421
422 vector<any::TSIG>::const_iterator it;
423 vector<any::TSIG>::const_iterator it_end = compare_set.end();
424 for (it = compare_set.begin(); it != it_end - 1; ++it) {
425 EXPECT_GT(0, (*it).compare(*(it + 1)));
426 EXPECT_LT(0, (*(it + 1)).compare(*it));
427 }
428
429 // comparison attempt between incompatible RR types should be rejected
430 EXPECT_THROW(rdata_tsig.compare(*RdataTest::rdata_nomatch), bad_cast);
431 }
432 }
433