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 = *&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