3 PowerDNS Versatile Database Driven Nameserver
4 Copyright (C) 2013 - 2015 PowerDNS.COM BV
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2
8 as published by the Free Software Foundation
10 Additionally, the license of this program contains a special
11 exception which allows to distribute the program in binary form when
12 it is linked against OpenSSL.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #ifndef BOOST_TEST_DYN_LINK
25 #define BOOST_TEST_DYN_LINK
28 #define BOOST_TEST_NO_MAIN
34 #include <boost/test/unit_test.hpp>
36 #include "dnssecinfra.hh"
37 #include "dnswriter.hh"
39 #include "tsigverifier.hh"
41 BOOST_AUTO_TEST_SUITE(test_tsig
)
43 static vector
<uint8_t> generateTSIGQuery(const DNSName
& qname
, const DNSName
& tsigName
, const DNSName
& tsigAlgo
, const string
& tsigSecret
, uint16_t fudge
=300, time_t tsigTime
=time(nullptr))
45 vector
<uint8_t> packet
;
46 DNSPacketWriter
pw(packet
, qname
, QType::A
);
49 pw
.getHeader()->id
=42;
50 pw
.startRecord(qname
, QType::A
);
51 pw
.xfr32BitInt(0x01020304);
58 tt
.secret
= tsigSecret
;
61 BOOST_REQUIRE(getTSIGHashEnum(tt
.algo
, the
));
63 TSIGRecordContent trc
;
64 trc
.d_algoName
= getTSIGAlgoName(the
);
65 trc
.d_time
= tsigTime
;
67 trc
.d_origID
= ntohs(pw
.getHeader()->id
);
70 addTSIG(pw
, trc
, tt
.name
, tt
.secret
, "", false);
74 static void checkTSIG(const DNSName
& tsigName
, const DNSName
& tsigAlgo
, const string
& tsigSecret
, const vector
<uint8_t>& packet
, const string
* overrideMac
=nullptr, uint16_t* overrideExtendedRCode
=nullptr, uint16_t* overrideOrigID
=nullptr)
76 string
packetStr(reinterpret_cast<const char*>(packet
.data()), packet
.size());
77 MOADNSParser
mdp(true, packetStr
);
79 bool tsigFound
= false;
82 TSIGRecordContent trc
;
84 for(const auto& answer
: mdp
.d_answers
) {
85 if(answer
.first
.d_type
== QType::TSIG
) {
86 BOOST_CHECK_EQUAL(answer
.first
.d_place
, DNSResourceRecord::ADDITIONAL
);
87 BOOST_CHECK_EQUAL(answer
.first
.d_class
, QClass::ANY
);
88 BOOST_CHECK_EQUAL(answer
.first
.d_ttl
, 0U);
89 BOOST_CHECK_EQUAL(tsigFound
, false);
91 auto rectrc
= getRR
<TSIGRecordContent
>(answer
.first
);
94 theirMac
= rectrc
->d_mac
;
95 keyName
= answer
.first
.d_name
;
102 theirMac
= *overrideMac
;
105 if (overrideOrigID
) {
106 trc
.d_origID
= *overrideOrigID
;
109 if (overrideExtendedRCode
) {
110 trc
.d_eRcode
= *overrideExtendedRCode
;
113 BOOST_REQUIRE(tsigFound
);
117 tt
.secret
= tsigSecret
;
119 BOOST_CHECK(validateTSIG(packetStr
, mdp
.getTSIGPos(), tt
, trc
, "", theirMac
, false));
122 BOOST_AUTO_TEST_CASE(test_TSIG_valid
) {
123 DNSName
tsigName("tsig.name");
124 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
125 DNSName
qname("test.valid.tsig");
126 string
tsigSecret("verysecret");
128 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
130 checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
);}
133 BOOST_AUTO_TEST_CASE(test_TSIG_different_case_algo
) {
134 DNSName
tsigName("tsig.name");
135 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
136 DNSName
qname("test.valid.tsig");
137 string
tsigSecret("verysecret");
139 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
141 checkTSIG(tsigName
, tsigAlgo
.makeLowerCase(), tsigSecret
, packet
);
144 BOOST_AUTO_TEST_CASE(test_TSIG_different_name_same_algo
) {
145 DNSName
tsigName("tsig.name");
146 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
147 DNSName
qname("test.valid.tsig");
148 string
tsigSecret("verysecret");
150 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
152 checkTSIG(tsigName
, DNSName("hmac-md5."), tsigSecret
, packet
);
155 BOOST_AUTO_TEST_CASE(test_TSIG_bad_key_name
) {
156 DNSName
tsigName("tsig.name");
157 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
158 DNSName
qname("test.valid.tsig");
159 string
tsigSecret("verysecret");
161 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
163 BOOST_CHECK_THROW(checkTSIG(DNSName("another.tsig.key.name"), tsigAlgo
, tsigSecret
, packet
), std::runtime_error
);
166 BOOST_AUTO_TEST_CASE(test_TSIG_bad_algo
) {
167 DNSName
tsigName("tsig.name");
168 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
169 DNSName
qname("test.valid.tsig");
170 string
tsigSecret("verysecret");
172 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
174 BOOST_CHECK_THROW(checkTSIG(tsigName
, DNSName("hmac-sha512."), tsigSecret
, packet
), std::runtime_error
);
177 BOOST_AUTO_TEST_CASE(test_TSIG_bad_secret
) {
178 DNSName
tsigName("tsig.name");
179 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
180 DNSName
qname("test.valid.tsig");
181 string
tsigSecret("verysecret");
183 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
185 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, "bad secret", packet
), std::runtime_error
);
188 BOOST_AUTO_TEST_CASE(test_TSIG_bad_ercode
) {
189 DNSName
tsigName("tsig.name");
190 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
191 DNSName
qname("test.valid.tsig");
192 string
tsigSecret("verysecret");
194 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
195 uint16_t badERcode
= 1;
197 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
, nullptr, &badERcode
), std::runtime_error
);
200 BOOST_AUTO_TEST_CASE(test_TSIG_bad_origID
) {
201 DNSName
tsigName("tsig.name");
202 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
203 DNSName
qname("test.valid.tsig");
204 string
tsigSecret("verysecret");
206 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
207 uint16_t badOrigID
= 1;
209 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
, nullptr, nullptr, &badOrigID
), std::runtime_error
);
212 BOOST_AUTO_TEST_CASE(test_TSIG_bad_mac
) {
213 DNSName
tsigName("tsig.name");
214 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
215 DNSName
qname("test.valid.tsig");
216 string
tsigSecret("verysecret");
218 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
220 string badMac
= "badmac";
221 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
, &badMac
), std::runtime_error
);
224 BOOST_AUTO_TEST_CASE(test_TSIG_signature_expired
) {
225 DNSName
tsigName("tsig.name");
226 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
227 DNSName
qname("test.valid.tsig");
228 string
tsigSecret("verysecret");
230 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
, 5, time(nullptr) - 10);
232 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
), std::runtime_error
);
235 BOOST_AUTO_TEST_CASE(test_TSIG_signature_too_far_in_the_future
) {
236 DNSName
tsigName("tsig.name");
237 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
238 DNSName
qname("test.valid.tsig");
239 string
tsigSecret("verysecret");
241 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
, 5, time(nullptr) + 20);
243 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
), std::runtime_error
);
246 BOOST_AUTO_TEST_SUITE_END();