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 #define BOOST_TEST_DYN_LINK
25 #define BOOST_TEST_NO_MAIN
31 #include <boost/test/unit_test.hpp>
33 #include "dnssecinfra.hh"
34 #include "dnswriter.hh"
36 #include "tsigverifier.hh"
38 BOOST_AUTO_TEST_SUITE(test_tsig
)
40 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))
42 vector
<uint8_t> packet
;
43 DNSPacketWriter
pw(packet
, qname
, QType::A
);
46 pw
.getHeader()->id
=42;
47 pw
.startRecord(qname
, QType::A
);
48 pw
.xfr32BitInt(0x01020304);
55 tt
.secret
= tsigSecret
;
58 BOOST_REQUIRE(getTSIGHashEnum(tt
.algo
, the
));
60 TSIGRecordContent trc
;
61 trc
.d_algoName
= getTSIGAlgoName(the
);
62 trc
.d_time
= tsigTime
;
64 trc
.d_origID
= ntohs(pw
.getHeader()->id
);
67 addTSIG(pw
, trc
, tt
.name
, tt
.secret
, "", false);
71 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)
73 string
packetStr(reinterpret_cast<const char*>(packet
.data()), packet
.size());
74 MOADNSParser
mdp(true, packetStr
);
76 bool tsigFound
= false;
79 TSIGRecordContent trc
;
81 for(const auto& answer
: mdp
.d_answers
) {
82 if(answer
.first
.d_type
== QType::TSIG
) {
83 BOOST_CHECK_EQUAL(answer
.first
.d_place
, DNSResourceRecord::ADDITIONAL
);
84 BOOST_CHECK_EQUAL(answer
.first
.d_class
, QClass::ANY
);
85 BOOST_CHECK_EQUAL(answer
.first
.d_ttl
, 0);
86 BOOST_CHECK_EQUAL(tsigFound
, false);
88 shared_ptr
<TSIGRecordContent
> rectrc
= getRR
<TSIGRecordContent
>(answer
.first
);
91 theirMac
= rectrc
->d_mac
;
92 keyName
= answer
.first
.d_name
;
99 theirMac
= *overrideMac
;
102 if (overrideOrigID
) {
103 trc
.d_origID
= *overrideOrigID
;
106 if (overrideExtendedRCode
) {
107 trc
.d_eRcode
= *overrideExtendedRCode
;
110 BOOST_REQUIRE(tsigFound
);
114 tt
.secret
= tsigSecret
;
116 BOOST_CHECK(validateTSIG(packetStr
, mdp
.getTSIGPos(), tt
, trc
, "", theirMac
, false));
119 BOOST_AUTO_TEST_CASE(test_TSIG_valid
) {
120 DNSName
tsigName("tsig.name");
121 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
122 DNSName
qname("test.valid.tsig");
123 string
tsigSecret("verysecret");
125 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
127 checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
);}
130 BOOST_AUTO_TEST_CASE(test_TSIG_different_case_algo
) {
131 DNSName
tsigName("tsig.name");
132 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
133 DNSName
qname("test.valid.tsig");
134 string
tsigSecret("verysecret");
136 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
138 checkTSIG(tsigName
, tsigAlgo
.makeLowerCase(), tsigSecret
, packet
);
141 BOOST_AUTO_TEST_CASE(test_TSIG_different_name_same_algo
) {
142 DNSName
tsigName("tsig.name");
143 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
144 DNSName
qname("test.valid.tsig");
145 string
tsigSecret("verysecret");
147 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
149 checkTSIG(tsigName
, DNSName("hmac-md5."), tsigSecret
, packet
);
152 BOOST_AUTO_TEST_CASE(test_TSIG_bad_key_name
) {
153 DNSName
tsigName("tsig.name");
154 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
155 DNSName
qname("test.valid.tsig");
156 string
tsigSecret("verysecret");
158 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
160 BOOST_CHECK_THROW(checkTSIG(DNSName("another.tsig.key.name"), tsigAlgo
, tsigSecret
, packet
), std::runtime_error
);
163 BOOST_AUTO_TEST_CASE(test_TSIG_bad_algo
) {
164 DNSName
tsigName("tsig.name");
165 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
166 DNSName
qname("test.valid.tsig");
167 string
tsigSecret("verysecret");
169 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
171 BOOST_CHECK_THROW(checkTSIG(tsigName
, DNSName("hmac-sha512."), tsigSecret
, packet
), std::runtime_error
);
174 BOOST_AUTO_TEST_CASE(test_TSIG_bad_secret
) {
175 DNSName
tsigName("tsig.name");
176 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
177 DNSName
qname("test.valid.tsig");
178 string
tsigSecret("verysecret");
180 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
182 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, "bad secret", packet
), std::runtime_error
);
185 BOOST_AUTO_TEST_CASE(test_TSIG_bad_ercode
) {
186 DNSName
tsigName("tsig.name");
187 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
188 DNSName
qname("test.valid.tsig");
189 string
tsigSecret("verysecret");
191 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
192 uint16_t badERcode
= 1;
194 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
, nullptr, &badERcode
), std::runtime_error
);
197 BOOST_AUTO_TEST_CASE(test_TSIG_bad_origID
) {
198 DNSName
tsigName("tsig.name");
199 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
200 DNSName
qname("test.valid.tsig");
201 string
tsigSecret("verysecret");
203 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
204 uint16_t badOrigID
= 1;
206 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
, nullptr, nullptr, &badOrigID
), std::runtime_error
);
209 BOOST_AUTO_TEST_CASE(test_TSIG_bad_mac
) {
210 DNSName
tsigName("tsig.name");
211 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
212 DNSName
qname("test.valid.tsig");
213 string
tsigSecret("verysecret");
215 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
);
217 string badMac
= "badmac";
218 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
, &badMac
), std::runtime_error
);
221 BOOST_AUTO_TEST_CASE(test_TSIG_signature_expired
) {
222 DNSName
tsigName("tsig.name");
223 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
224 DNSName
qname("test.valid.tsig");
225 string
tsigSecret("verysecret");
227 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
, 5, time(nullptr) - 10);
229 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
), std::runtime_error
);
232 BOOST_AUTO_TEST_CASE(test_TSIG_signature_too_far_in_the_future
) {
233 DNSName
tsigName("tsig.name");
234 DNSName
tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
235 DNSName
qname("test.valid.tsig");
236 string
tsigSecret("verysecret");
238 vector
<uint8_t> packet
= generateTSIGQuery(qname
, tsigName
, tsigAlgo
, tsigSecret
, 5, time(nullptr) + 20);
240 BOOST_CHECK_THROW(checkTSIG(tsigName
, tsigAlgo
, tsigSecret
, packet
), std::runtime_error
);
243 BOOST_AUTO_TEST_SUITE_END();