]>
Commit | Line | Data |
---|---|---|
ea3816cf RG |
1 | |
2 | /* | |
3 | PowerDNS Versatile Database Driven Nameserver | |
4 | Copyright (C) 2013 - 2015 PowerDNS.COM BV | |
5 | ||
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 | |
9 | ||
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. | |
13 | ||
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. | |
18 | ||
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 | |
22 | */ | |
23 | ||
1c2d079d | 24 | #ifndef BOOST_TEST_DYN_LINK |
ea3816cf | 25 | #define BOOST_TEST_DYN_LINK |
1c2d079d FM |
26 | #endif |
27 | ||
ea3816cf RG |
28 | #define BOOST_TEST_NO_MAIN |
29 | ||
30 | #ifdef HAVE_CONFIG_H | |
31 | #include "config.h" | |
32 | #endif | |
33 | ||
34 | #include <boost/test/unit_test.hpp> | |
35 | ||
36 | #include "dnssecinfra.hh" | |
37 | #include "dnswriter.hh" | |
38 | #include "misc.hh" | |
39 | #include "tsigverifier.hh" | |
40 | ||
c7f29d3e | 41 | BOOST_AUTO_TEST_SUITE(test_tsig) |
ea3816cf RG |
42 | |
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)) | |
44 | { | |
45 | vector<uint8_t> packet; | |
46 | DNSPacketWriter pw(packet, qname, QType::A); | |
47 | pw.getHeader()->qr=0; | |
48 | pw.getHeader()->rd=0; | |
49 | pw.getHeader()->id=42; | |
50 | pw.startRecord(qname, QType::A); | |
51 | pw.xfr32BitInt(0x01020304); | |
52 | pw.addOpt(512, 0, 0); | |
53 | pw.commit(); | |
54 | ||
55 | TSIGTriplet tt; | |
56 | tt.name = tsigName; | |
57 | tt.algo = tsigAlgo; | |
58 | tt.secret = tsigSecret; | |
59 | ||
60 | TSIGHashEnum the; | |
61 | BOOST_REQUIRE(getTSIGHashEnum(tt.algo, the)); | |
62 | ||
63 | TSIGRecordContent trc; | |
64 | trc.d_algoName = getTSIGAlgoName(the); | |
65 | trc.d_time = tsigTime; | |
66 | trc.d_fudge = fudge; | |
67 | trc.d_origID = ntohs(pw.getHeader()->id); | |
68 | trc.d_eRcode = 0; | |
69 | ||
70 | addTSIG(pw, trc, tt.name, tt.secret, "", false); | |
71 | return packet; | |
72 | } | |
73 | ||
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) | |
75 | { | |
76 | string packetStr(reinterpret_cast<const char*>(packet.data()), packet.size()); | |
77 | MOADNSParser mdp(true, packetStr); | |
78 | ||
79 | bool tsigFound = false; | |
80 | string theirMac; | |
81 | DNSName keyName; | |
82 | TSIGRecordContent trc; | |
83 | ||
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); | |
690b86b7 | 88 | BOOST_CHECK_EQUAL(answer.first.d_ttl, 0U); |
ea3816cf RG |
89 | BOOST_CHECK_EQUAL(tsigFound, false); |
90 | ||
d06dcda4 | 91 | auto rectrc = getRR<TSIGRecordContent>(answer.first); |
ea3816cf RG |
92 | if (rectrc) { |
93 | trc = *rectrc; | |
94 | theirMac = rectrc->d_mac; | |
95 | keyName = answer.first.d_name; | |
96 | tsigFound = true; | |
97 | } | |
98 | } | |
99 | } | |
100 | ||
101 | if (overrideMac) { | |
102 | theirMac = *overrideMac; | |
103 | } | |
104 | ||
105 | if (overrideOrigID) { | |
106 | trc.d_origID = *overrideOrigID; | |
107 | } | |
108 | ||
109 | if (overrideExtendedRCode) { | |
110 | trc.d_eRcode = *overrideExtendedRCode; | |
111 | } | |
112 | ||
113 | BOOST_REQUIRE(tsigFound); | |
114 | TSIGTriplet tt; | |
115 | tt.name = tsigName; | |
116 | tt.algo = tsigAlgo; | |
117 | tt.secret = tsigSecret; | |
118 | ||
119 | BOOST_CHECK(validateTSIG(packetStr, mdp.getTSIGPos(), tt, trc, "", theirMac, false)); | |
120 | } | |
121 | ||
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"); | |
127 | ||
128 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
129 | ||
130 | checkTSIG(tsigName, tsigAlgo, tsigSecret, packet);} | |
131 | ||
132 | ||
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"); | |
138 | ||
139 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
140 | ||
141 | checkTSIG(tsigName, tsigAlgo.makeLowerCase(), tsigSecret, packet); | |
142 | } | |
143 | ||
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"); | |
149 | ||
150 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
151 | ||
152 | checkTSIG(tsigName, DNSName("hmac-md5."), tsigSecret, packet); | |
153 | } | |
154 | ||
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"); | |
160 | ||
161 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
162 | ||
163 | BOOST_CHECK_THROW(checkTSIG(DNSName("another.tsig.key.name"), tsigAlgo, tsigSecret, packet), std::runtime_error); | |
164 | } | |
165 | ||
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"); | |
171 | ||
172 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
173 | ||
174 | BOOST_CHECK_THROW(checkTSIG(tsigName, DNSName("hmac-sha512."), tsigSecret, packet), std::runtime_error); | |
175 | } | |
176 | ||
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"); | |
182 | ||
183 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
184 | ||
185 | BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, "bad secret", packet), std::runtime_error); | |
186 | } | |
187 | ||
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"); | |
193 | ||
194 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
195 | uint16_t badERcode = 1; | |
196 | ||
197 | BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet, nullptr, &badERcode), std::runtime_error); | |
198 | } | |
199 | ||
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"); | |
205 | ||
206 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
207 | uint16_t badOrigID = 1; | |
208 | ||
209 | BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet, nullptr, nullptr, &badOrigID), std::runtime_error); | |
210 | } | |
211 | ||
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"); | |
217 | ||
218 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); | |
219 | ||
220 | string badMac = "badmac"; | |
221 | BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet, &badMac), std::runtime_error); | |
222 | } | |
223 | ||
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"); | |
229 | ||
230 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret, 5, time(nullptr) - 10); | |
231 | ||
232 | BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet), std::runtime_error); | |
233 | } | |
234 | ||
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"); | |
240 | ||
241 | vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret, 5, time(nullptr) + 20); | |
242 | ||
243 | BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet), std::runtime_error); | |
244 | } | |
245 | ||
246 | BOOST_AUTO_TEST_SUITE_END(); |