]>
Commit | Line | Data |
---|---|---|
1c2d079d | 1 | #ifndef BOOST_TEST_DYN_LINK |
86675669 | 2 | #define BOOST_TEST_DYN_LINK |
1c2d079d FM |
3 | #endif |
4 | ||
86675669 OM |
5 | #include <boost/test/unit_test.hpp> |
6 | ||
7 | #include "test-syncres_cc.hh" | |
8 | ||
9 | BOOST_AUTO_TEST_SUITE(syncres_cc4) | |
10 | ||
42dcf516 OM |
11 | BOOST_AUTO_TEST_CASE(test_auth_zone_nodata) |
12 | { | |
86675669 OM |
13 | std::unique_ptr<SyncRes> sr; |
14 | initSR(sr); | |
15 | ||
16 | primeHints(); | |
17 | ||
18 | size_t queriesCount = 0; | |
19 | const DNSName target("nodata.powerdns.com."); | |
20 | const DNSName authZone("powerdns.com"); | |
21 | ||
22 | SyncRes::AuthDomain ad; | |
23 | ad.d_name = authZone; | |
24 | DNSRecord dr; | |
25 | dr.d_place = DNSResourceRecord::ANSWER; | |
26 | dr.d_name = target; | |
27 | dr.d_type = QType::A; | |
28 | dr.d_ttl = 3600; | |
d06dcda4 | 29 | dr.setContent(std::make_shared<ARecordContent>(ComboAddress("192.0.2.1"))); |
86675669 OM |
30 | ad.d_records.insert(dr); |
31 | ||
32 | dr.d_place = DNSResourceRecord::ANSWER; | |
33 | dr.d_name = authZone; | |
34 | dr.d_type = QType::SOA; | |
35 | dr.d_ttl = 3600; | |
d06dcda4 | 36 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
86675669 OM |
37 | ad.d_records.insert(dr); |
38 | ||
39 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
40 | (*map)[authZone] = ad; | |
41 | SyncRes::setDomainMap(map); | |
42 | ||
c5e86860 | 43 | sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* /* res */, bool* /* chained */) { |
42dcf516 | 44 | queriesCount++; |
86675669 | 45 | |
308f4c43 | 46 | return LWResult::Result::Timeout; |
86675669 OM |
47 | }); |
48 | ||
49 | vector<DNSRecord> ret; | |
50 | int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret); | |
51 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
690b86b7 | 52 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
86675669 | 53 | BOOST_CHECK(ret[0].d_type == QType::SOA); |
690b86b7 | 54 | BOOST_CHECK_EQUAL(queriesCount, 0U); |
86675669 OM |
55 | } |
56 | ||
42dcf516 OM |
57 | BOOST_AUTO_TEST_CASE(test_auth_zone_nx) |
58 | { | |
86675669 OM |
59 | std::unique_ptr<SyncRes> sr; |
60 | initSR(sr); | |
61 | ||
62 | primeHints(); | |
63 | ||
64 | size_t queriesCount = 0; | |
65 | const DNSName target("nx.powerdns.com."); | |
66 | const DNSName authZone("powerdns.com"); | |
67 | ||
68 | SyncRes::AuthDomain ad; | |
69 | ad.d_name = authZone; | |
70 | DNSRecord dr; | |
71 | dr.d_place = DNSResourceRecord::ANSWER; | |
72 | dr.d_name = DNSName("powerdns.com."); | |
73 | dr.d_type = QType::SOA; | |
74 | dr.d_ttl = 3600; | |
d06dcda4 | 75 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
86675669 OM |
76 | ad.d_records.insert(dr); |
77 | ||
78 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
79 | (*map)[authZone] = ad; | |
80 | SyncRes::setDomainMap(map); | |
81 | ||
c5e86860 | 82 | sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* /* res */, bool* /* chained */) { |
42dcf516 | 83 | queriesCount++; |
86675669 | 84 | |
308f4c43 | 85 | return LWResult::Result::Timeout; |
86675669 OM |
86 | }); |
87 | ||
88 | vector<DNSRecord> ret; | |
89 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
90 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
690b86b7 | 91 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
86675669 | 92 | BOOST_CHECK(ret[0].d_type == QType::SOA); |
690b86b7 | 93 | BOOST_CHECK_EQUAL(queriesCount, 0U); |
86675669 OM |
94 | } |
95 | ||
42dcf516 OM |
96 | BOOST_AUTO_TEST_CASE(test_auth_zone_delegation) |
97 | { | |
86675669 | 98 | std::unique_ptr<SyncRes> sr; |
399e1209 | 99 | initSR(sr, true); |
86675669 OM |
100 | |
101 | primeHints(); | |
102 | ||
103 | size_t queriesCount = 0; | |
104 | const DNSName target("www.test.powerdns.com."); | |
105 | const ComboAddress targetAddr("192.0.2.2"); | |
106 | const DNSName ns("ns1.test.powerdns.com."); | |
107 | const ComboAddress nsAddr("192.0.2.1"); | |
108 | const DNSName authZone("powerdns.com"); | |
109 | ||
110 | SyncRes::AuthDomain ad; | |
111 | ad.d_name = authZone; | |
112 | DNSRecord dr; | |
113 | dr.d_place = DNSResourceRecord::ANSWER; | |
114 | dr.d_name = authZone; | |
115 | dr.d_type = QType::SOA; | |
116 | dr.d_ttl = 3600; | |
d06dcda4 | 117 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
86675669 OM |
118 | ad.d_records.insert(dr); |
119 | ||
120 | dr.d_place = DNSResourceRecord::ANSWER; | |
121 | dr.d_name = DNSName("test.powerdns.com."); | |
122 | dr.d_type = QType::NS; | |
123 | dr.d_ttl = 3600; | |
d06dcda4 | 124 | dr.setContent(std::make_shared<NSRecordContent>(ns)); |
86675669 OM |
125 | ad.d_records.insert(dr); |
126 | ||
127 | dr.d_place = DNSResourceRecord::ANSWER; | |
128 | dr.d_name = ns; | |
129 | dr.d_type = QType::A; | |
130 | dr.d_ttl = 3600; | |
d06dcda4 | 131 | dr.setContent(std::make_shared<ARecordContent>(nsAddr)); |
86675669 OM |
132 | ad.d_records.insert(dr); |
133 | ||
134 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
135 | (*map)[authZone] = ad; | |
136 | SyncRes::setDomainMap(map); | |
137 | ||
138 | testkeysset_t keys; | |
139 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
140 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 | 141 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); |
86675669 OM |
142 | g_luaconfs.setState(luaconfsCopy); |
143 | ||
7ced0738 RG |
144 | /* make sure that the signature inception and validity times are computed |
145 | based on the SyncRes time, not the current one, in case the function | |
146 | takes too long. */ | |
147 | const time_t fixedNow = sr->getNow().tv_sec; | |
148 | ||
c0f8e484 | 149 | sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 OM |
150 | queriesCount++; |
151 | if (type == QType::DS || type == QType::DNSKEY) { | |
399e1209 | 152 | return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys, domain == DNSName("com.") || domain == authZone, fixedNow); |
42dcf516 | 153 | } |
86675669 | 154 | |
c0f8e484 | 155 | if (address == ComboAddress(nsAddr.toString(), 53) && domain == target) { |
42dcf516 OM |
156 | setLWResult(res, 0, true, false, true); |
157 | addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600); | |
308f4c43 | 158 | return LWResult::Result::Success; |
42dcf516 | 159 | } |
86675669 | 160 | |
308f4c43 | 161 | return LWResult::Result::Timeout; |
86675669 OM |
162 | }); |
163 | ||
164 | sr->setDNSSECValidationRequested(true); | |
165 | vector<DNSRecord> ret; | |
166 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
167 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
690b86b7 | 168 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
86675669 | 169 | BOOST_CHECK(ret[0].d_type == QType::A); |
7c1fe83b | 170 | BOOST_CHECK_EQUAL(queriesCount, 1U); |
98307d0f | 171 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate); |
86675669 OM |
172 | } |
173 | ||
42dcf516 OM |
174 | BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point) |
175 | { | |
86675669 OM |
176 | std::unique_ptr<SyncRes> sr; |
177 | initSR(sr); | |
178 | ||
179 | primeHints(); | |
180 | ||
181 | size_t queriesCount = 0; | |
182 | const DNSName target("test.powerdns.com."); | |
183 | const ComboAddress targetAddr("192.0.2.2"); | |
184 | const DNSName ns("ns1.test.powerdns.com."); | |
185 | const ComboAddress nsAddr("192.0.2.1"); | |
186 | const DNSName authZone("powerdns.com"); | |
187 | ||
188 | SyncRes::AuthDomain ad; | |
189 | ad.d_name = authZone; | |
190 | DNSRecord dr; | |
191 | dr.d_place = DNSResourceRecord::ANSWER; | |
192 | dr.d_name = authZone; | |
193 | dr.d_type = QType::SOA; | |
194 | dr.d_ttl = 3600; | |
d06dcda4 | 195 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
86675669 OM |
196 | ad.d_records.insert(dr); |
197 | ||
198 | dr.d_place = DNSResourceRecord::ANSWER; | |
199 | dr.d_name = DNSName("test.powerdns.com."); | |
200 | dr.d_type = QType::NS; | |
201 | dr.d_ttl = 3600; | |
d06dcda4 | 202 | dr.setContent(std::make_shared<NSRecordContent>(ns)); |
86675669 OM |
203 | ad.d_records.insert(dr); |
204 | ||
205 | dr.d_place = DNSResourceRecord::ANSWER; | |
206 | dr.d_name = ns; | |
207 | dr.d_type = QType::A; | |
208 | dr.d_ttl = 3600; | |
d06dcda4 | 209 | dr.setContent(std::make_shared<ARecordContent>(nsAddr)); |
86675669 OM |
210 | ad.d_records.insert(dr); |
211 | ||
212 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
213 | (*map)[authZone] = ad; | |
214 | SyncRes::setDomainMap(map); | |
215 | ||
c0f8e484 | 216 | sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 217 | queriesCount++; |
86675669 | 218 | |
c0f8e484 | 219 | if (address == ComboAddress(nsAddr.toString(), 53) && domain == target) { |
42dcf516 OM |
220 | setLWResult(res, 0, true, false, true); |
221 | addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600); | |
308f4c43 | 222 | return LWResult::Result::Success; |
42dcf516 | 223 | } |
86675669 | 224 | |
308f4c43 | 225 | return LWResult::Result::Timeout; |
86675669 OM |
226 | }); |
227 | ||
228 | vector<DNSRecord> ret; | |
229 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
230 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
690b86b7 | 231 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
86675669 | 232 | BOOST_CHECK(ret[0].d_type == QType::A); |
690b86b7 | 233 | BOOST_CHECK_EQUAL(queriesCount, 1U); |
86675669 OM |
234 | } |
235 | ||
42dcf516 OM |
236 | BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard) |
237 | { | |
86675669 OM |
238 | std::unique_ptr<SyncRes> sr; |
239 | initSR(sr); | |
240 | ||
241 | primeHints(); | |
242 | ||
243 | size_t queriesCount = 0; | |
244 | const DNSName target("test.powerdns.com."); | |
245 | const ComboAddress targetAddr("192.0.2.2"); | |
246 | const DNSName authZone("powerdns.com"); | |
247 | ||
248 | SyncRes::AuthDomain ad; | |
249 | ad.d_name = authZone; | |
250 | DNSRecord dr; | |
251 | dr.d_place = DNSResourceRecord::ANSWER; | |
252 | dr.d_name = authZone; | |
253 | dr.d_type = QType::SOA; | |
254 | dr.d_ttl = 3600; | |
d06dcda4 | 255 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
86675669 OM |
256 | ad.d_records.insert(dr); |
257 | ||
258 | dr.d_place = DNSResourceRecord::ANSWER; | |
259 | dr.d_name = DNSName("*.powerdns.com."); | |
260 | dr.d_type = QType::A; | |
261 | dr.d_ttl = 3600; | |
d06dcda4 | 262 | dr.setContent(std::make_shared<ARecordContent>(targetAddr)); |
86675669 OM |
263 | ad.d_records.insert(dr); |
264 | ||
265 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
266 | (*map)[authZone] = ad; | |
267 | SyncRes::setDomainMap(map); | |
268 | ||
c5e86860 | 269 | sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* /* res */, bool* /* chained */) { |
42dcf516 | 270 | queriesCount++; |
86675669 | 271 | |
308f4c43 | 272 | return LWResult::Result::Timeout; |
86675669 OM |
273 | }); |
274 | ||
275 | vector<DNSRecord> ret; | |
276 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
277 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
690b86b7 | 278 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
86675669 | 279 | BOOST_CHECK(ret[0].d_type == QType::A); |
690b86b7 | 280 | BOOST_CHECK_EQUAL(queriesCount, 0U); |
86675669 OM |
281 | } |
282 | ||
42dcf516 OM |
283 | BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_with_ent) |
284 | { | |
91e18d5d OM |
285 | std::unique_ptr<SyncRes> sr; |
286 | initSR(sr); | |
287 | ||
288 | primeHints(); | |
289 | ||
290 | size_t queriesCount = 0; | |
291 | const DNSName target("test.powerdns.com."); | |
292 | const ComboAddress targetAddr1("192.0.2.1"); | |
293 | const ComboAddress targetAddr2("192.0.2.2"); | |
294 | const DNSName authZone("powerdns.com"); | |
295 | ||
296 | SyncRes::AuthDomain ad; | |
297 | ad.d_name = authZone; | |
298 | DNSRecord dr; | |
299 | dr.d_place = DNSResourceRecord::ANSWER; | |
300 | dr.d_name = authZone; | |
301 | dr.d_type = QType::SOA; | |
302 | dr.d_ttl = 3600; | |
d06dcda4 | 303 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
91e18d5d OM |
304 | ad.d_records.insert(dr); |
305 | ||
306 | dr.d_place = DNSResourceRecord::ANSWER; | |
307 | dr.d_name = DNSName("abc.xyz.test.powerdns.com."); | |
308 | dr.d_type = QType::A; | |
309 | dr.d_ttl = 3600; | |
d06dcda4 | 310 | dr.setContent(std::make_shared<ARecordContent>(targetAddr1)); |
91e18d5d OM |
311 | ad.d_records.insert(dr); |
312 | ||
313 | dr.d_place = DNSResourceRecord::ANSWER; | |
314 | dr.d_name = DNSName("*.powerdns.com."); | |
315 | dr.d_type = QType::A; | |
316 | dr.d_ttl = 3600; | |
d06dcda4 | 317 | dr.setContent(std::make_shared<ARecordContent>(targetAddr2)); |
91e18d5d OM |
318 | ad.d_records.insert(dr); |
319 | ||
320 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
321 | (*map)[authZone] = ad; | |
322 | SyncRes::setDomainMap(map); | |
323 | ||
c5e86860 | 324 | sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* /* res */, bool* /* chained */) { |
42dcf516 | 325 | queriesCount++; |
91e18d5d | 326 | |
308f4c43 | 327 | return LWResult::Result::Timeout; |
91e18d5d OM |
328 | }); |
329 | ||
330 | vector<DNSRecord> ret; | |
331 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
332 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
690b86b7 | 333 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
42dcf516 | 334 | |
0e42f5cc OM |
335 | // WARN below should be changed to CHECK once the issue is fixed. |
336 | const string m("Please fix issue #8312"); | |
337 | BOOST_WARN_MESSAGE(ret[0].d_type == QType::SOA, m); | |
690b86b7 | 338 | BOOST_CHECK_EQUAL(queriesCount, 0U); |
91e18d5d OM |
339 | } |
340 | ||
42dcf516 OM |
341 | BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata) |
342 | { | |
86675669 OM |
343 | std::unique_ptr<SyncRes> sr; |
344 | initSR(sr); | |
345 | ||
346 | primeHints(); | |
347 | ||
348 | size_t queriesCount = 0; | |
349 | const DNSName target("test.powerdns.com."); | |
350 | const ComboAddress targetAddr("192.0.2.2"); | |
351 | const DNSName authZone("powerdns.com"); | |
352 | ||
353 | SyncRes::AuthDomain ad; | |
354 | ad.d_name = authZone; | |
355 | DNSRecord dr; | |
356 | dr.d_place = DNSResourceRecord::ANSWER; | |
357 | dr.d_name = authZone; | |
358 | dr.d_type = QType::SOA; | |
359 | dr.d_ttl = 3600; | |
d06dcda4 | 360 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
86675669 OM |
361 | ad.d_records.insert(dr); |
362 | ||
363 | dr.d_place = DNSResourceRecord::ANSWER; | |
364 | dr.d_name = DNSName("*.powerdns.com."); | |
365 | dr.d_type = QType::A; | |
366 | dr.d_ttl = 3600; | |
d06dcda4 | 367 | dr.setContent(std::make_shared<ARecordContent>(targetAddr)); |
86675669 OM |
368 | ad.d_records.insert(dr); |
369 | ||
370 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
371 | (*map)[authZone] = ad; | |
372 | SyncRes::setDomainMap(map); | |
373 | ||
c5e86860 | 374 | sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* /* res */, bool* /* chained */) { |
42dcf516 | 375 | queriesCount++; |
86675669 | 376 | |
308f4c43 | 377 | return LWResult::Result::Timeout; |
86675669 OM |
378 | }); |
379 | ||
380 | vector<DNSRecord> ret; | |
381 | int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret); | |
382 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
690b86b7 | 383 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
86675669 | 384 | BOOST_CHECK(ret[0].d_type == QType::SOA); |
690b86b7 | 385 | BOOST_CHECK_EQUAL(queriesCount, 0U); |
86675669 OM |
386 | } |
387 | ||
42dcf516 OM |
388 | BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only) |
389 | { | |
86675669 OM |
390 | std::unique_ptr<SyncRes> sr; |
391 | initSR(sr); | |
392 | ||
393 | primeHints(); | |
394 | ||
395 | size_t queriesCount = 0; | |
396 | const DNSName target("powerdns.com."); | |
397 | const ComboAddress addr("192.0.2.5"); | |
398 | ||
399 | SyncRes::AuthDomain ad; | |
400 | ad.d_name = target; | |
401 | DNSRecord dr; | |
402 | dr.d_place = DNSResourceRecord::ANSWER; | |
403 | dr.d_name = target; | |
404 | dr.d_type = QType::SOA; | |
405 | dr.d_ttl = 3600; | |
d06dcda4 | 406 | dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600")); |
86675669 OM |
407 | ad.d_records.insert(dr); |
408 | ||
409 | dr.d_place = DNSResourceRecord::ANSWER; | |
410 | dr.d_name = target; | |
411 | dr.d_type = QType::A; | |
412 | dr.d_ttl = 3600; | |
d06dcda4 | 413 | dr.setContent(std::make_shared<ARecordContent>(addr)); |
86675669 OM |
414 | ad.d_records.insert(dr); |
415 | ||
416 | auto map = std::make_shared<SyncRes::domainmap_t>(); | |
417 | (*map)[target] = ad; | |
418 | SyncRes::setDomainMap(map); | |
419 | ||
c5e86860 | 420 | sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 OM |
421 | queriesCount++; |
422 | setLWResult(res, 0, true, false, true); | |
423 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
308f4c43 | 424 | return LWResult::Result::Success; |
86675669 OM |
425 | }); |
426 | ||
427 | /* simulate a no-RD query */ | |
428 | sr->setCacheOnly(); | |
429 | ||
430 | vector<DNSRecord> ret; | |
431 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
432 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
690b86b7 | 433 | BOOST_CHECK_EQUAL(ret.size(), 1U); |
86675669 OM |
434 | BOOST_CHECK(ret[0].d_type == QType::A); |
435 | BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString()); | |
690b86b7 | 436 | BOOST_CHECK_EQUAL(queriesCount, 0U); |
86675669 OM |
437 | } |
438 | ||
42dcf516 OM |
439 | BOOST_AUTO_TEST_CASE(test_dnssec_rrsig) |
440 | { | |
86675669 OM |
441 | initSR(); |
442 | ||
a2c6e554 | 443 | auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 | 444 | dcke->create(dcke->getBits()); |
86675669 | 445 | DNSSECPrivateKey dpk; |
a456662f | 446 | dpk.setKey(std::move(dcke), 256); |
86675669 | 447 | |
c1e7b833 RG |
448 | sortedRecords_t recordcontents; |
449 | recordcontents.insert(getRecordContent(QType::A, "192.0.2.1")); | |
86675669 OM |
450 | |
451 | DNSName qname("powerdns.com."); | |
452 | ||
453 | time_t now = time(nullptr); | |
454 | RRSIGRecordContent rrc; | |
455 | /* this RRSIG is valid for the current second only */ | |
456 | computeRRSIG(dpk, qname, qname, QType::A, 600, 0, rrc, recordcontents, boost::none, now); | |
457 | ||
458 | skeyset_t keyset; | |
459 | keyset.insert(std::make_shared<DNSKEYRecordContent>(dpk.getDNSKEY())); | |
460 | ||
d06dcda4 | 461 | std::vector<std::shared_ptr<const RRSIGRecordContent>> sigs; |
86675669 OM |
462 | sigs.push_back(std::make_shared<RRSIGRecordContent>(rrc)); |
463 | ||
15e973d6 OM |
464 | pdns::validation::ValidationContext validationContext; |
465 | BOOST_CHECK(validateWithKeySet(now, qname, recordcontents, sigs, keyset, std::nullopt, validationContext) == vState::Secure); | |
466 | BOOST_CHECK_EQUAL(validationContext.d_validationsCounter, 1U); | |
86675669 OM |
467 | } |
468 | ||
42dcf516 OM |
469 | BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk) |
470 | { | |
86675669 OM |
471 | std::unique_ptr<SyncRes> sr; |
472 | initSR(sr, true); | |
473 | ||
474 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
475 | ||
476 | primeHints(); | |
477 | const DNSName target("."); | |
478 | testkeysset_t keys; | |
479 | ||
480 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
481 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 | 482 | generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors); |
86675669 OM |
483 | g_luaconfs.setState(luaconfsCopy); |
484 | ||
485 | size_t queriesCount = 0; | |
486 | ||
c0f8e484 | 487 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 488 | queriesCount++; |
86675669 | 489 | |
42dcf516 | 490 | if (domain == target && type == QType::NS) { |
86675669 | 491 | |
42dcf516 OM |
492 | setLWResult(res, 0, true, false, true); |
493 | char addr[] = "a.root-servers.net."; | |
494 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
495 | addr[0] = idx; | |
496 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
497 | } | |
86675669 | 498 | |
42dcf516 | 499 | addRRSIG(keys, res->d_records, domain, 300); |
86675669 | 500 | |
42dcf516 OM |
501 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
502 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 503 | |
308f4c43 | 504 | return LWResult::Result::Success; |
42dcf516 | 505 | } |
c0f8e484 | 506 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 507 | |
42dcf516 | 508 | setLWResult(res, 0, true, false, true); |
86675669 | 509 | |
42dcf516 OM |
510 | addDNSKEY(keys, domain, 300, res->d_records); |
511 | addRRSIG(keys, res->d_records, domain, 300); | |
86675669 | 512 | |
308f4c43 | 513 | return LWResult::Result::Success; |
42dcf516 | 514 | } |
86675669 | 515 | |
308f4c43 | 516 | return LWResult::Result::Timeout; |
42dcf516 | 517 | }); |
86675669 OM |
518 | |
519 | vector<DNSRecord> ret; | |
520 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
521 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 522 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure); |
86675669 | 523 | /* 13 NS + 1 RRSIG */ |
690b86b7 OM |
524 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
525 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
526 | |
527 | /* again, to test the cache */ | |
528 | ret.clear(); | |
529 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
530 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 531 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure); |
690b86b7 OM |
532 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
533 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
534 | } |
535 | ||
42dcf516 OM |
536 | BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk) |
537 | { | |
86675669 OM |
538 | std::unique_ptr<SyncRes> sr; |
539 | initSR(sr, true); | |
540 | ||
541 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
542 | ||
543 | primeHints(); | |
544 | const DNSName target("."); | |
545 | testkeysset_t zskeys; | |
546 | testkeysset_t kskeys; | |
547 | ||
548 | /* Generate key material for "." */ | |
a2c6e554 | 549 | auto dckeZ = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 OM |
550 | dckeZ->create(dckeZ->getBits()); |
551 | DNSSECPrivateKey ksk; | |
a456662f | 552 | ksk.setKey(std::move(dckeZ), 257); |
690b86b7 | 553 | DSRecordContent kskds = makeDSFromDNSKey(target, ksk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
86675669 | 554 | |
a2c6e554 | 555 | auto dckeK = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 OM |
556 | dckeK->create(dckeK->getBits()); |
557 | DNSSECPrivateKey zsk; | |
a456662f | 558 | zsk.setKey(std::move(dckeK), 256); |
690b86b7 | 559 | DSRecordContent zskds = makeDSFromDNSKey(target, zsk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
86675669 | 560 | |
42dcf516 OM |
561 | kskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(ksk, kskds); |
562 | zskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(zsk, zskds); | |
86675669 OM |
563 | |
564 | /* Set the root DS */ | |
565 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
566 | luaconfsCopy.dsAnchors.clear(); | |
567 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(kskds); | |
568 | g_luaconfs.setState(luaconfsCopy); | |
569 | ||
570 | size_t queriesCount = 0; | |
571 | ||
c0f8e484 | 572 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 573 | queriesCount++; |
86675669 | 574 | |
42dcf516 | 575 | if (domain == target && type == QType::NS) { |
86675669 | 576 | |
42dcf516 OM |
577 | setLWResult(res, 0, true, false, true); |
578 | char addr[] = "a.root-servers.net."; | |
579 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
580 | addr[0] = idx; | |
581 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
582 | } | |
86675669 | 583 | |
42dcf516 | 584 | addRRSIG(zskeys, res->d_records, domain, 300); |
86675669 | 585 | |
42dcf516 OM |
586 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
587 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 588 | |
308f4c43 | 589 | return LWResult::Result::Success; |
42dcf516 | 590 | } |
c0f8e484 | 591 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 592 | |
42dcf516 | 593 | setLWResult(res, 0, true, false, true); |
86675669 | 594 | |
42dcf516 OM |
595 | addDNSKEY(kskeys, domain, 300, res->d_records); |
596 | addDNSKEY(zskeys, domain, 300, res->d_records); | |
597 | addRRSIG(kskeys, res->d_records, domain, 300); | |
86675669 | 598 | |
308f4c43 | 599 | return LWResult::Result::Success; |
42dcf516 | 600 | } |
86675669 | 601 | |
308f4c43 | 602 | return LWResult::Result::Timeout; |
42dcf516 | 603 | }); |
86675669 OM |
604 | |
605 | vector<DNSRecord> ret; | |
606 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
607 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 608 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure); |
86675669 | 609 | /* 13 NS + 1 RRSIG */ |
690b86b7 OM |
610 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
611 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
612 | |
613 | /* again, to test the cache */ | |
614 | ret.clear(); | |
615 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
616 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 617 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure); |
690b86b7 OM |
618 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
619 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
620 | } |
621 | ||
42dcf516 OM |
622 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey) |
623 | { | |
86675669 OM |
624 | std::unique_ptr<SyncRes> sr; |
625 | initSR(sr, true); | |
626 | ||
627 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
628 | ||
629 | primeHints(); | |
630 | const DNSName target("."); | |
631 | testkeysset_t keys; | |
632 | ||
633 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
634 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 | 635 | generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors); |
86675669 OM |
636 | g_luaconfs.setState(luaconfsCopy); |
637 | ||
638 | size_t queriesCount = 0; | |
639 | ||
c0f8e484 | 640 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 641 | queriesCount++; |
86675669 | 642 | |
42dcf516 | 643 | if (domain == target && type == QType::NS) { |
86675669 | 644 | |
42dcf516 OM |
645 | setLWResult(res, 0, true, false, true); |
646 | char addr[] = "a.root-servers.net."; | |
647 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
648 | addr[0] = idx; | |
649 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
650 | } | |
86675669 | 651 | |
42dcf516 | 652 | addRRSIG(keys, res->d_records, domain, 300); |
86675669 | 653 | |
42dcf516 OM |
654 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
655 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 656 | |
308f4c43 | 657 | return LWResult::Result::Success; |
42dcf516 | 658 | } |
c0f8e484 | 659 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 660 | |
42dcf516 | 661 | setLWResult(res, 0, true, false, true); |
86675669 | 662 | |
42dcf516 | 663 | /* No DNSKEY */ |
86675669 | 664 | |
308f4c43 | 665 | return LWResult::Result::Success; |
42dcf516 | 666 | } |
86675669 | 667 | |
308f4c43 | 668 | return LWResult::Result::Timeout; |
42dcf516 | 669 | }); |
86675669 OM |
670 | |
671 | vector<DNSRecord> ret; | |
672 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
673 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 674 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication); |
86675669 | 675 | /* 13 NS + 1 RRSIG */ |
690b86b7 OM |
676 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
677 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
678 | |
679 | /* again, to test the cache */ | |
680 | ret.clear(); | |
681 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
682 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 683 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication); |
690b86b7 OM |
684 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
685 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
686 | } |
687 | ||
6f2088b4 RG |
688 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_without_zone_flag) |
689 | { | |
690 | std::unique_ptr<SyncRes> sr; | |
691 | initSR(sr, true); | |
692 | ||
693 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
694 | ||
695 | primeHints(); | |
696 | const DNSName target("."); | |
697 | testkeysset_t keys; | |
698 | ||
699 | /* Generate key material for "." */ | |
a2c6e554 | 700 | auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
6f2088b4 RG |
701 | dcke->create(dcke->getBits()); |
702 | DNSSECPrivateKey csk; | |
a456662f | 703 | csk.setKey(std::move(dcke), 0); |
6f2088b4 RG |
704 | DSRecordContent ds = makeDSFromDNSKey(target, csk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
705 | ||
706 | keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(csk, ds); | |
707 | ||
708 | /* Set the root DS */ | |
709 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
710 | luaconfsCopy.dsAnchors.clear(); | |
711 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(ds); | |
712 | g_luaconfs.setState(luaconfsCopy); | |
713 | ||
714 | size_t queriesCount = 0; | |
715 | ||
c0f8e484 | 716 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
6f2088b4 RG |
717 | queriesCount++; |
718 | ||
719 | if (domain == target && type == QType::NS) { | |
720 | ||
721 | setLWResult(res, 0, true, false, true); | |
722 | char addr[] = "a.root-servers.net."; | |
723 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
724 | addr[0] = idx; | |
725 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
726 | } | |
727 | ||
728 | addRRSIG(keys, res->d_records, domain, 300); | |
729 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
730 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
731 | ||
308f4c43 | 732 | return LWResult::Result::Success; |
6f2088b4 | 733 | } |
c0f8e484 | 734 | if (domain == target && type == QType::DNSKEY) { |
6f2088b4 RG |
735 | |
736 | setLWResult(res, 0, true, false, true); | |
737 | ||
738 | addDNSKEY(keys, domain, 300, res->d_records); | |
739 | addRRSIG(keys, res->d_records, domain, 300); | |
740 | ||
308f4c43 | 741 | return LWResult::Result::Success; |
6f2088b4 RG |
742 | } |
743 | ||
308f4c43 | 744 | return LWResult::Result::Timeout; |
6f2088b4 RG |
745 | }); |
746 | ||
747 | vector<DNSRecord> ret; | |
748 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
749 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fecac3ba | 750 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoZoneKeyBitSet); |
6f2088b4 RG |
751 | /* 13 NS + 1 RRSIG */ |
752 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); | |
753 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
754 | ||
755 | /* again, to test the cache */ | |
756 | ret.clear(); | |
757 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
758 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fecac3ba | 759 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoZoneKeyBitSet); |
6f2088b4 RG |
760 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
761 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
762 | } | |
763 | ||
764 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_revoked) | |
765 | { | |
766 | std::unique_ptr<SyncRes> sr; | |
767 | initSR(sr, true); | |
768 | ||
769 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
770 | ||
771 | primeHints(); | |
772 | const DNSName target("."); | |
773 | testkeysset_t keys; | |
774 | ||
775 | /* Generate key material for "." */ | |
a2c6e554 | 776 | auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
6f2088b4 RG |
777 | dcke->create(dcke->getBits()); |
778 | DNSSECPrivateKey csk; | |
a456662f | 779 | csk.setKey(std::move(dcke), 257 | 128); |
6f2088b4 RG |
780 | DSRecordContent ds = makeDSFromDNSKey(target, csk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
781 | ||
782 | keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(csk, ds); | |
783 | ||
784 | /* Set the root DS */ | |
785 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
786 | luaconfsCopy.dsAnchors.clear(); | |
787 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(ds); | |
788 | g_luaconfs.setState(luaconfsCopy); | |
789 | ||
790 | size_t queriesCount = 0; | |
791 | ||
c0f8e484 | 792 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
6f2088b4 RG |
793 | queriesCount++; |
794 | ||
795 | if (domain == target && type == QType::NS) { | |
796 | ||
797 | setLWResult(res, 0, true, false, true); | |
798 | char addr[] = "a.root-servers.net."; | |
799 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
800 | addr[0] = idx; | |
801 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
802 | } | |
803 | ||
804 | addRRSIG(keys, res->d_records, domain, 300); | |
805 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
806 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
807 | ||
308f4c43 | 808 | return LWResult::Result::Success; |
6f2088b4 | 809 | } |
c0f8e484 | 810 | if (domain == target && type == QType::DNSKEY) { |
6f2088b4 RG |
811 | |
812 | setLWResult(res, 0, true, false, true); | |
813 | ||
814 | addDNSKEY(keys, domain, 300, res->d_records); | |
815 | addRRSIG(keys, res->d_records, domain, 300); | |
816 | ||
308f4c43 | 817 | return LWResult::Result::Success; |
6f2088b4 RG |
818 | } |
819 | ||
308f4c43 | 820 | return LWResult::Result::Timeout; |
6f2088b4 RG |
821 | }); |
822 | ||
823 | vector<DNSRecord> ret; | |
824 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
825 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fecac3ba | 826 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusRevokedDNSKEY); |
6f2088b4 RG |
827 | /* 13 NS + 1 RRSIG */ |
828 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); | |
829 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
830 | ||
831 | /* again, to test the cache */ | |
832 | ret.clear(); | |
833 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
834 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fecac3ba | 835 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusRevokedDNSKEY); |
6f2088b4 RG |
836 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
837 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
838 | } | |
15e973d6 | 839 | |
42dcf516 OM |
840 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds) |
841 | { | |
86675669 OM |
842 | std::unique_ptr<SyncRes> sr; |
843 | initSR(sr, true); | |
844 | ||
453f3773 | 845 | setDNSSECValidation(sr, DNSSECMode::Process); |
86675669 OM |
846 | |
847 | primeHints(); | |
848 | const DNSName target("."); | |
849 | testkeysset_t dskeys; | |
850 | testkeysset_t keys; | |
851 | ||
852 | /* Generate key material for "." */ | |
a2c6e554 | 853 | auto dckeDS = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 OM |
854 | dckeDS->create(dckeDS->getBits()); |
855 | DNSSECPrivateKey dskey; | |
a456662f | 856 | dskey.setKey(std::move(dckeDS), 257); |
690b86b7 | 857 | DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
86675669 | 858 | |
a2c6e554 | 859 | auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 OM |
860 | dcke->create(dcke->getBits()); |
861 | DNSSECPrivateKey dpk; | |
a456662f | 862 | dpk.setKey(std::move(dcke), 256); |
15e973d6 | 863 | DSRecordContent seconddrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
86675669 | 864 | |
42dcf516 | 865 | dskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dskey, drc); |
15e973d6 | 866 | keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, seconddrc); |
86675669 OM |
867 | |
868 | /* Set the root DS */ | |
869 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
870 | luaconfsCopy.dsAnchors.clear(); | |
871 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc); | |
872 | g_luaconfs.setState(luaconfsCopy); | |
873 | ||
874 | size_t queriesCount = 0; | |
875 | ||
c0f8e484 | 876 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 877 | queriesCount++; |
86675669 | 878 | |
42dcf516 | 879 | if (domain == target && type == QType::NS) { |
86675669 | 880 | |
42dcf516 OM |
881 | setLWResult(res, 0, true, false, true); |
882 | char addr[] = "a.root-servers.net."; | |
883 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
884 | addr[0] = idx; | |
885 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
886 | } | |
86675669 | 887 | |
42dcf516 | 888 | addRRSIG(keys, res->d_records, domain, 300); |
86675669 | 889 | |
42dcf516 OM |
890 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
891 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 892 | |
308f4c43 | 893 | return LWResult::Result::Success; |
42dcf516 | 894 | } |
c0f8e484 | 895 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 896 | |
42dcf516 | 897 | setLWResult(res, 0, true, false, true); |
86675669 | 898 | |
42dcf516 OM |
899 | addDNSKEY(keys, domain, 300, res->d_records); |
900 | addRRSIG(keys, res->d_records, domain, 300); | |
86675669 | 901 | |
308f4c43 | 902 | return LWResult::Result::Success; |
42dcf516 | 903 | } |
86675669 | 904 | |
308f4c43 | 905 | return LWResult::Result::Timeout; |
42dcf516 | 906 | }); |
86675669 | 907 | |
453f3773 RG |
908 | /* === with validation enabled === */ |
909 | sr->setDNSSECValidationRequested(true); | |
86675669 OM |
910 | vector<DNSRecord> ret; |
911 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
912 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 913 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY); |
86675669 | 914 | /* 13 NS + 1 RRSIG */ |
690b86b7 OM |
915 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
916 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
917 | |
918 | /* again, to test the cache */ | |
919 | ret.clear(); | |
920 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
921 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 922 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY); |
690b86b7 OM |
923 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
924 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
453f3773 RG |
925 | |
926 | /* === first without validation, then with (just-in-time validation) === */ | |
927 | /* clear the caches */ | |
2bbc9eb0 RP |
928 | g_recCache = std::make_unique<MemRecursorCache>(); |
929 | g_negCache = std::make_unique<NegCache>(); | |
453f3773 RG |
930 | sr->setDNSSECValidationRequested(false); |
931 | primeHints(); | |
932 | ||
933 | ret.clear(); | |
934 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
935 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 936 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate); |
453f3773 RG |
937 | /* 13 NS + 1 RRSIG */ |
938 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); | |
939 | BOOST_CHECK_EQUAL(queriesCount, 3U); | |
940 | ||
941 | /* now we ask for the DNSKEYs (still without validation) */ | |
942 | ret.clear(); | |
943 | res = sr->beginResolve(target, QType(QType::DNSKEY), QClass::IN, ret); | |
944 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 945 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate); |
453f3773 RG |
946 | /* 1 SOA + 1 RRSIG */ |
947 | BOOST_REQUIRE_EQUAL(ret.size(), 2U); | |
948 | BOOST_CHECK_EQUAL(queriesCount, 4U); | |
949 | ||
950 | /* again, to test the cache WITH validation */ | |
951 | sr->setDNSSECValidationRequested(true); | |
952 | ret.clear(); | |
953 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
954 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 955 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY); |
453f3773 RG |
956 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
957 | BOOST_CHECK_EQUAL(queriesCount, 4U); | |
86675669 OM |
958 | } |
959 | ||
15e973d6 OM |
960 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_dss) |
961 | { | |
962 | std::unique_ptr<SyncRes> sr; | |
963 | initSR(sr, true); | |
964 | ||
965 | setDNSSECValidation(sr, DNSSECMode::Process); | |
966 | ||
967 | primeHints(); | |
968 | const DNSName target("."); | |
969 | testkeysset_t keys; | |
970 | ||
971 | g_maxDSsToConsider = 1; | |
972 | ||
973 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
974 | luaconfsCopy.dsAnchors.clear(); | |
975 | /* generate more DSs for the zone than we are willing to consider: only the last one will be used to generate DNSKEY records */ | |
976 | for (size_t idx = 0; idx < (g_maxDSsToConsider + 10U); idx++) { | |
977 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); | |
978 | } | |
979 | g_luaconfs.setState(luaconfsCopy); | |
980 | ||
981 | size_t queriesCount = 0; | |
982 | ||
983 | sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) { | |
984 | queriesCount++; | |
985 | ||
986 | if (domain == target && type == QType::NS) { | |
987 | ||
988 | setLWResult(res, 0, true, false, true); | |
989 | char addr[] = "a.root-servers.net."; | |
990 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
991 | addr[0] = idx; | |
992 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
993 | } | |
994 | ||
995 | addRRSIG(keys, res->d_records, domain, 300); | |
996 | ||
997 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
998 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
999 | ||
1000 | return LWResult::Result::Success; | |
1001 | } | |
1002 | else if (domain == target && type == QType::DNSKEY) { | |
1003 | ||
1004 | setLWResult(res, 0, true, false, true); | |
1005 | ||
1006 | addDNSKEY(keys, domain, 300, res->d_records); | |
1007 | addRRSIG(keys, res->d_records, domain, 300); | |
1008 | ||
1009 | return LWResult::Result::Success; | |
1010 | } | |
1011 | ||
1012 | return LWResult::Result::Timeout; | |
1013 | }); | |
1014 | ||
1015 | /* === with validation enabled === */ | |
1016 | sr->setDNSSECValidationRequested(true); | |
1017 | vector<DNSRecord> ret; | |
1018 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1019 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1020 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY); | |
1021 | /* 13 NS + 1 RRSIG */ | |
1022 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); | |
1023 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1024 | ||
1025 | /* again, to test the cache */ | |
1026 | ret.clear(); | |
1027 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1028 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1029 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY); | |
1030 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); | |
1031 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1032 | ||
1033 | g_maxDNSKEYsToConsider = 0; | |
1034 | } | |
1035 | ||
1036 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_dnskeys) | |
1037 | { | |
1038 | std::unique_ptr<SyncRes> sr; | |
1039 | initSR(sr, true); | |
1040 | ||
1041 | setDNSSECValidation(sr, DNSSECMode::Process); | |
1042 | ||
1043 | primeHints(); | |
1044 | const DNSName target("."); | |
1045 | testkeysset_t dskeys; | |
1046 | testkeysset_t keys; | |
1047 | ||
1048 | DNSKEYRecordContent dnskeyRecordContent; | |
1049 | dnskeyRecordContent.d_algorithm = 13; | |
1050 | /* Generate key material for "." */ | |
1051 | auto dckeDS = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2 | |
1052 | Algorithm: 13 (ECDSAP256SHA256) | |
1053 | PrivateKey: Ovj4pzrSh0U6aEVoKaPFhK1D4NMG0xrymj9+6TpwC8o=)PKEY"); | |
1054 | DNSSECPrivateKey dskey; | |
1055 | dskey.setKey(std::move(dckeDS), 257); | |
1056 | assert(dskey.getTag() == 31337); | |
1057 | DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); | |
1058 | dskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dskey, drc); | |
1059 | ||
1060 | /* Different key, same tag */ | |
1061 | auto dcke = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2 | |
1062 | Algorithm: 13 (ECDSAP256SHA256) | |
1063 | PrivateKey: n7SRA4n6NejhZBWQOhjTaICYSpkTl6plJn1ATFG23FI=)PKEY"); | |
1064 | DNSSECPrivateKey dpk; | |
1065 | dpk.setKey(std::move(dcke), 256); | |
1066 | assert(dpk.getTag() == dskey.getTag()); | |
1067 | DSRecordContent uselessdrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); | |
1068 | keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, uselessdrc); | |
1069 | ||
1070 | /* Set the root DS (one of them!) */ | |
1071 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1072 | luaconfsCopy.dsAnchors.clear(); | |
1073 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc); | |
1074 | g_luaconfs.setState(luaconfsCopy); | |
1075 | ||
1076 | size_t queriesCount = 0; | |
1077 | ||
1078 | sr->setAsyncCallback([target, &queriesCount, keys, dskeys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) { | |
1079 | queriesCount++; | |
1080 | ||
1081 | if (domain == target && type == QType::NS) { | |
1082 | ||
1083 | setLWResult(res, 0, true, false, true); | |
1084 | char addr[] = "a.root-servers.net."; | |
1085 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1086 | addr[0] = idx; | |
1087 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1088 | } | |
1089 | ||
1090 | addRRSIG(dskeys, res->d_records, domain, 300); | |
1091 | ||
1092 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
1093 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
1094 | ||
1095 | return LWResult::Result::Success; | |
1096 | } | |
1097 | else if (domain == target && type == QType::DNSKEY) { | |
1098 | ||
1099 | setLWResult(res, 0, true, false, true); | |
1100 | ||
1101 | addDNSKEY(keys, domain, 300, res->d_records); | |
1102 | addDNSKEY(dskeys, domain, 300, res->d_records); | |
1103 | addRRSIG(keys, res->d_records, domain, 300); | |
1104 | addRRSIG(dskeys, res->d_records, domain, 300); | |
1105 | ||
1106 | return LWResult::Result::Success; | |
1107 | } | |
1108 | ||
1109 | return LWResult::Result::Timeout; | |
1110 | }); | |
1111 | ||
1112 | g_maxDNSKEYsToConsider = 1; | |
1113 | ||
1114 | /* === with validation enabled === */ | |
1115 | sr->setDNSSECValidationRequested(true); | |
1116 | vector<DNSRecord> ret; | |
1117 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1118 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1119 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY); | |
1120 | /* 13 NS + 1 RRSIG */ | |
1121 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); | |
1122 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1123 | ||
1124 | /* again, to test the cache */ | |
1125 | ret.clear(); | |
1126 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1127 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1128 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY); | |
1129 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); | |
1130 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1131 | ||
1132 | g_maxDNSKEYsToConsider = 0; | |
1133 | } | |
1134 | ||
1135 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_dnskeys_while_checking_signature) | |
1136 | { | |
1137 | std::unique_ptr<SyncRes> sr; | |
1138 | initSR(sr, true); | |
1139 | ||
1140 | setDNSSECValidation(sr, DNSSECMode::Process); | |
1141 | ||
1142 | primeHints(); | |
1143 | const DNSName target("."); | |
1144 | testkeysset_t dskeys; | |
1145 | testkeysset_t keys; | |
1146 | testkeysset_t otherkeys; | |
1147 | ||
1148 | DNSKEYRecordContent dnskeyRecordContent; | |
1149 | dnskeyRecordContent.d_algorithm = 13; | |
1150 | /* Generate key material for "." */ | |
1151 | auto dckeDS = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2 | |
1152 | Algorithm: 13 (ECDSAP256SHA256) | |
1153 | PrivateKey: Ovj4pzrSh0U6aEVoKaPFhK1D4NMG0xrymj9+6TpwC8o=)PKEY"); | |
1154 | DNSSECPrivateKey dskey; | |
1155 | dskey.setKey(std::move(dckeDS), 257); | |
1156 | assert(dskey.getTag() == 31337); | |
1157 | DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); | |
1158 | dskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dskey, drc); | |
1159 | ||
1160 | /* Different key, same tag */ | |
1161 | auto dcke = DNSCryptoKeyEngine::makeFromISCString(dnskeyRecordContent, R"PKEY(Private-key-format: v1.2 | |
1162 | Algorithm: 13 (ECDSAP256SHA256) | |
1163 | PrivateKey: pTaMJcvNrPIIiQiHGvCLZZASroyQpUwew5FvCgjHNsk=)PKEY"); | |
1164 | DNSSECPrivateKey dpk; | |
1165 | // why 258, you may ask? We need this record to be sorted AFTER the other one in a sortedRecords_t | |
1166 | // so that the validation of the DNSKEY rrset succeeds | |
1167 | dpk.setKey(std::move(dcke), 258); | |
1168 | assert(dpk.getTag() == dskey.getTag()); | |
1169 | DSRecordContent uselessdrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); | |
1170 | keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, uselessdrc); | |
1171 | ||
1172 | /* Set the root DSs (only one of them) */ | |
1173 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1174 | luaconfsCopy.dsAnchors.clear(); | |
1175 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc); | |
1176 | g_luaconfs.setState(luaconfsCopy); | |
1177 | ||
1178 | size_t queriesCount = 0; | |
1179 | ||
1180 | sr->setAsyncCallback([target, &queriesCount, keys, dskeys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) { | |
1181 | queriesCount++; | |
1182 | ||
1183 | if (domain == target && type == QType::NS) { | |
1184 | ||
1185 | setLWResult(res, 0, true, false, true); | |
1186 | char addr[] = "a.root-servers.net."; | |
1187 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1188 | addr[0] = idx; | |
1189 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1190 | } | |
1191 | ||
1192 | addRRSIG(keys, res->d_records, domain, 300); | |
1193 | addRRSIG(dskeys, res->d_records, domain, 300); | |
1194 | ||
1195 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
1196 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
1197 | ||
1198 | return LWResult::Result::Success; | |
1199 | } | |
1200 | else if (domain == target && type == QType::DNSKEY) { | |
1201 | ||
1202 | setLWResult(res, 0, true, false, true); | |
1203 | ||
1204 | addDNSKEY(dskeys, domain, 300, res->d_records); | |
1205 | addDNSKEY(keys, domain, 300, res->d_records); | |
1206 | addRRSIG(dskeys, res->d_records, domain, 300); | |
1207 | ||
1208 | return LWResult::Result::Success; | |
1209 | } | |
1210 | ||
1211 | return LWResult::Result::Timeout; | |
1212 | }); | |
1213 | ||
1214 | g_maxDNSKEYsToConsider = 1; | |
1215 | ||
1216 | /* === with validation enabled === */ | |
1217 | sr->setDNSSECValidationRequested(true); | |
1218 | vector<DNSRecord> ret; | |
1219 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1220 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1221 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); | |
1222 | /* 13 NS + 1 RRSIG */ | |
1223 | BOOST_REQUIRE_EQUAL(ret.size(), 15U); | |
1224 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1225 | ||
1226 | /* again, to test the cache */ | |
1227 | ret.clear(); | |
1228 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1229 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1230 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); | |
1231 | BOOST_REQUIRE_EQUAL(ret.size(), 15U); | |
1232 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1233 | ||
1234 | g_maxDNSKEYsToConsider = 0; | |
1235 | } | |
1236 | ||
42dcf516 OM |
1237 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey) |
1238 | { | |
86675669 OM |
1239 | std::unique_ptr<SyncRes> sr; |
1240 | initSR(sr, true); | |
1241 | ||
1242 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1243 | ||
1244 | primeHints(); | |
1245 | const DNSName target("."); | |
1246 | testkeysset_t keys; | |
1247 | testkeysset_t rrsigkeys; | |
1248 | ||
1249 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1250 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 | 1251 | generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors); |
86675669 OM |
1252 | g_luaconfs.setState(luaconfsCopy); |
1253 | ||
a2c6e554 | 1254 | auto dckeRRSIG = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 OM |
1255 | dckeRRSIG->create(dckeRRSIG->getBits()); |
1256 | DNSSECPrivateKey rrsigkey; | |
a456662f | 1257 | rrsigkey.setKey(std::move(dckeRRSIG), 257); |
690b86b7 | 1258 | DSRecordContent rrsigds = makeDSFromDNSKey(target, rrsigkey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
86675669 | 1259 | |
42dcf516 | 1260 | rrsigkeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(rrsigkey, rrsigds); |
86675669 OM |
1261 | |
1262 | size_t queriesCount = 0; | |
1263 | ||
c0f8e484 | 1264 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 1265 | queriesCount++; |
86675669 | 1266 | |
42dcf516 | 1267 | if (domain == target && type == QType::NS) { |
86675669 | 1268 | |
42dcf516 OM |
1269 | setLWResult(res, 0, true, false, true); |
1270 | char addr[] = "a.root-servers.net."; | |
1271 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1272 | addr[0] = idx; | |
1273 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1274 | } | |
86675669 | 1275 | |
42dcf516 | 1276 | addRRSIG(rrsigkeys, res->d_records, domain, 300); |
86675669 | 1277 | |
42dcf516 OM |
1278 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
1279 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 1280 | |
308f4c43 | 1281 | return LWResult::Result::Success; |
42dcf516 | 1282 | } |
c0f8e484 | 1283 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 1284 | |
42dcf516 | 1285 | setLWResult(res, 0, true, false, true); |
86675669 | 1286 | |
42dcf516 OM |
1287 | addDNSKEY(keys, domain, 300, res->d_records); |
1288 | addRRSIG(rrsigkeys, res->d_records, domain, 300); | |
86675669 | 1289 | |
308f4c43 | 1290 | return LWResult::Result::Success; |
42dcf516 | 1291 | } |
86675669 | 1292 | |
308f4c43 | 1293 | return LWResult::Result::Timeout; |
42dcf516 | 1294 | }); |
86675669 OM |
1295 | |
1296 | vector<DNSRecord> ret; | |
1297 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1298 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1299 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); |
86675669 | 1300 | /* 13 NS + 1 RRSIG */ |
690b86b7 OM |
1301 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1302 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
1303 | |
1304 | /* again, to test the cache */ | |
1305 | ret.clear(); | |
1306 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1307 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1308 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); |
690b86b7 OM |
1309 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1310 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
1311 | } |
1312 | ||
42dcf516 OM |
1313 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig) |
1314 | { | |
86675669 OM |
1315 | std::unique_ptr<SyncRes> sr; |
1316 | initSR(sr, true); | |
1317 | ||
1318 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1319 | ||
1320 | primeHints(); | |
1321 | const DNSName target("."); | |
1322 | testkeysset_t keys; | |
1323 | ||
1324 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1325 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 | 1326 | generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors); |
86675669 OM |
1327 | g_luaconfs.setState(luaconfsCopy); |
1328 | ||
1329 | size_t queriesCount = 0; | |
1330 | ||
c0f8e484 | 1331 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 1332 | queriesCount++; |
86675669 | 1333 | |
42dcf516 | 1334 | if (domain == target && type == QType::NS) { |
86675669 | 1335 | |
42dcf516 OM |
1336 | setLWResult(res, 0, true, false, true); |
1337 | char addr[] = "a.root-servers.net."; | |
1338 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1339 | addr[0] = idx; | |
1340 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 86400); | |
1341 | } | |
86675669 | 1342 | |
42dcf516 | 1343 | /* No RRSIG */ |
86675669 | 1344 | |
42dcf516 OM |
1345 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
1346 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
3f3b0086 RG |
1347 | |
1348 | return LWResult::Result::Success; | |
1349 | } | |
c0f8e484 | 1350 | if (domain == target && type == QType::DNSKEY) { |
3f3b0086 RG |
1351 | |
1352 | setLWResult(res, 0, true, false, true); | |
1353 | ||
1354 | addDNSKEY(keys, domain, 300, res->d_records); | |
1355 | addRRSIG(keys, res->d_records, domain, 300); | |
1356 | ||
1357 | return LWResult::Result::Success; | |
1358 | } | |
1359 | ||
1360 | return LWResult::Result::Timeout; | |
1361 | }); | |
1362 | ||
1363 | SyncRes::s_maxcachettl = 86400; | |
1364 | SyncRes::s_maxbogusttl = 3600; | |
1365 | ||
1366 | vector<DNSRecord> ret; | |
1367 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1368 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1369 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); | |
1370 | /* 13 NS + 0 RRSIG */ | |
1371 | BOOST_REQUIRE_EQUAL(ret.size(), 13U); | |
1372 | /* no RRSIG so no query for DNSKEYs */ | |
1373 | BOOST_CHECK_EQUAL(queriesCount, 1U); | |
1374 | ||
1375 | /* again, to test the cache */ | |
1376 | ret.clear(); | |
1377 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1378 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1379 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); | |
1380 | BOOST_REQUIRE_EQUAL(ret.size(), 13U); | |
1381 | /* check that we capped the TTL to max-cache-bogus-ttl */ | |
1382 | for (const auto& record : ret) { | |
1383 | BOOST_CHECK_LE(record.d_ttl, SyncRes::s_maxbogusttl); | |
1384 | } | |
1385 | BOOST_CHECK_EQUAL(queriesCount, 1U); | |
1386 | } | |
1387 | ||
1388 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig_noaa) | |
1389 | { | |
1390 | std::unique_ptr<SyncRes> sr; | |
1391 | initSR(sr, true); | |
1392 | ||
1393 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1394 | ||
1395 | primeHints(); | |
1396 | const DNSName target("."); | |
1397 | testkeysset_t keys; | |
1398 | ||
1399 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1400 | luaconfsCopy.dsAnchors.clear(); | |
1401 | generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors); | |
1402 | g_luaconfs.setState(luaconfsCopy); | |
1403 | ||
1404 | size_t queriesCount = 0; | |
1405 | ||
c0f8e484 | 1406 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
3f3b0086 RG |
1407 | queriesCount++; |
1408 | ||
1409 | if (domain == target && type == QType::NS) { | |
1410 | ||
1411 | /* We are not setting AA! */ | |
1412 | setLWResult(res, 0, false, false, true); | |
1413 | char addr[] = "a.root-servers.net."; | |
1414 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1415 | addr[0] = idx; | |
1416 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 86400); | |
1417 | } | |
1418 | ||
1419 | /* No RRSIG */ | |
1420 | ||
1421 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
1422 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 1423 | |
308f4c43 | 1424 | return LWResult::Result::Success; |
42dcf516 | 1425 | } |
c0f8e484 | 1426 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 1427 | |
42dcf516 | 1428 | setLWResult(res, 0, true, false, true); |
86675669 | 1429 | |
42dcf516 OM |
1430 | addDNSKEY(keys, domain, 300, res->d_records); |
1431 | addRRSIG(keys, res->d_records, domain, 300); | |
86675669 | 1432 | |
308f4c43 | 1433 | return LWResult::Result::Success; |
42dcf516 | 1434 | } |
86675669 | 1435 | |
308f4c43 | 1436 | return LWResult::Result::Timeout; |
42dcf516 | 1437 | }); |
86675669 OM |
1438 | |
1439 | SyncRes::s_maxcachettl = 86400; | |
1440 | SyncRes::s_maxbogusttl = 3600; | |
1441 | ||
1442 | vector<DNSRecord> ret; | |
1443 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1444 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1445 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); |
86675669 | 1446 | /* 13 NS + 0 RRSIG */ |
690b86b7 | 1447 | BOOST_REQUIRE_EQUAL(ret.size(), 13U); |
86675669 | 1448 | /* no RRSIG so no query for DNSKEYs */ |
690b86b7 | 1449 | BOOST_CHECK_EQUAL(queriesCount, 1U); |
86675669 OM |
1450 | |
1451 | /* again, to test the cache */ | |
1452 | ret.clear(); | |
1453 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1454 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1455 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); |
690b86b7 | 1456 | BOOST_REQUIRE_EQUAL(ret.size(), 13U); |
86675669 OM |
1457 | /* check that we capped the TTL to max-cache-bogus-ttl */ |
1458 | for (const auto& record : ret) { | |
1459 | BOOST_CHECK_LE(record.d_ttl, SyncRes::s_maxbogusttl); | |
1460 | } | |
690b86b7 | 1461 | BOOST_CHECK_EQUAL(queriesCount, 1U); |
86675669 OM |
1462 | } |
1463 | ||
42dcf516 OM |
1464 | BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm) |
1465 | { | |
86675669 OM |
1466 | std::unique_ptr<SyncRes> sr; |
1467 | initSR(sr, true); | |
1468 | ||
1469 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1470 | ||
1471 | primeHints(); | |
1472 | const DNSName target("."); | |
1473 | testkeysset_t keys; | |
1474 | ||
1475 | /* Generate key material for "." */ | |
a2c6e554 | 1476 | auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 OM |
1477 | dcke->create(dcke->getBits()); |
1478 | DNSSECPrivateKey dpk; | |
86675669 | 1479 | /* Fake algorithm number (private) */ |
c5153ca0 | 1480 | dpk.setKey(std::move(dcke), 256, 253); |
86675669 | 1481 | |
690b86b7 | 1482 | DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
42dcf516 | 1483 | keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc); |
86675669 OM |
1484 | /* Fake algorithm number (private) */ |
1485 | drc.d_algorithm = 253; | |
1486 | ||
1487 | /* Set the root DS */ | |
1488 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1489 | luaconfsCopy.dsAnchors.clear(); | |
1490 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc); | |
1491 | g_luaconfs.setState(luaconfsCopy); | |
1492 | ||
1493 | size_t queriesCount = 0; | |
1494 | ||
c0f8e484 | 1495 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 1496 | queriesCount++; |
86675669 | 1497 | |
42dcf516 | 1498 | if (domain == target && type == QType::NS) { |
86675669 | 1499 | |
42dcf516 OM |
1500 | setLWResult(res, 0, true, false, true); |
1501 | char addr[] = "a.root-servers.net."; | |
1502 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1503 | addr[0] = idx; | |
1504 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1505 | } | |
86675669 | 1506 | |
42dcf516 | 1507 | addRRSIG(keys, res->d_records, domain, 300); |
86675669 | 1508 | |
42dcf516 OM |
1509 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
1510 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 1511 | |
308f4c43 | 1512 | return LWResult::Result::Success; |
42dcf516 | 1513 | } |
c0f8e484 | 1514 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 1515 | |
42dcf516 | 1516 | setLWResult(res, 0, true, false, true); |
86675669 | 1517 | |
42dcf516 OM |
1518 | addDNSKEY(keys, domain, 300, res->d_records); |
1519 | addRRSIG(keys, res->d_records, domain, 300); | |
86675669 | 1520 | |
308f4c43 | 1521 | return LWResult::Result::Success; |
42dcf516 | 1522 | } |
86675669 | 1523 | |
308f4c43 | 1524 | return LWResult::Result::Timeout; |
42dcf516 | 1525 | }); |
86675669 OM |
1526 | |
1527 | vector<DNSRecord> ret; | |
1528 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1529 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 1530 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure); |
86675669 | 1531 | /* 13 NS + 1 RRSIG */ |
690b86b7 | 1532 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
86675669 | 1533 | /* no supported DS so no query for DNSKEYs */ |
690b86b7 | 1534 | BOOST_CHECK_EQUAL(queriesCount, 1U); |
86675669 OM |
1535 | |
1536 | /* again, to test the cache */ | |
1537 | ret.clear(); | |
1538 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1539 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 1540 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure); |
690b86b7 OM |
1541 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1542 | BOOST_CHECK_EQUAL(queriesCount, 1U); | |
86675669 OM |
1543 | } |
1544 | ||
42dcf516 OM |
1545 | BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest) |
1546 | { | |
86675669 OM |
1547 | std::unique_ptr<SyncRes> sr; |
1548 | initSR(sr, true); | |
1549 | ||
1550 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1551 | ||
1552 | primeHints(); | |
1553 | const DNSName target("."); | |
1554 | testkeysset_t keys; | |
1555 | ||
1556 | /* Generate key material for "." */ | |
a2c6e554 | 1557 | auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256); |
86675669 OM |
1558 | dcke->create(dcke->getBits()); |
1559 | DNSSECPrivateKey dpk; | |
a456662f | 1560 | dpk.setKey(std::move(dcke), 256); |
690b86b7 | 1561 | DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256); |
86675669 OM |
1562 | /* Fake digest number (reserved) */ |
1563 | drc.d_digesttype = 0; | |
1564 | ||
1565 | keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc); | |
1566 | ||
1567 | /* Set the root DS */ | |
1568 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1569 | luaconfsCopy.dsAnchors.clear(); | |
1570 | luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc); | |
1571 | g_luaconfs.setState(luaconfsCopy); | |
1572 | ||
1573 | size_t queriesCount = 0; | |
1574 | ||
c0f8e484 | 1575 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 1576 | queriesCount++; |
86675669 | 1577 | |
42dcf516 | 1578 | if (domain == target && type == QType::NS) { |
86675669 | 1579 | |
42dcf516 OM |
1580 | setLWResult(res, 0, true, false, true); |
1581 | char addr[] = "a.root-servers.net."; | |
1582 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1583 | addr[0] = idx; | |
1584 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1585 | } | |
86675669 | 1586 | |
42dcf516 | 1587 | addRRSIG(keys, res->d_records, domain, 300); |
86675669 | 1588 | |
42dcf516 OM |
1589 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
1590 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 1591 | |
308f4c43 | 1592 | return LWResult::Result::Success; |
42dcf516 | 1593 | } |
c0f8e484 | 1594 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 1595 | |
42dcf516 | 1596 | setLWResult(res, 0, true, false, true); |
86675669 | 1597 | |
42dcf516 OM |
1598 | addDNSKEY(keys, domain, 300, res->d_records); |
1599 | addRRSIG(keys, res->d_records, domain, 300); | |
86675669 | 1600 | |
308f4c43 | 1601 | return LWResult::Result::Success; |
42dcf516 | 1602 | } |
86675669 | 1603 | |
308f4c43 | 1604 | return LWResult::Result::Timeout; |
42dcf516 | 1605 | }); |
86675669 OM |
1606 | |
1607 | vector<DNSRecord> ret; | |
1608 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1609 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 1610 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure); |
86675669 | 1611 | /* 13 NS + 1 RRSIG */ |
690b86b7 | 1612 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
86675669 | 1613 | /* no supported DS so no query for DNSKEYs */ |
690b86b7 | 1614 | BOOST_CHECK_EQUAL(queriesCount, 1U); |
86675669 OM |
1615 | |
1616 | /* again, to test the cache */ | |
1617 | ret.clear(); | |
1618 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1619 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
98307d0f | 1620 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure); |
690b86b7 OM |
1621 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1622 | BOOST_CHECK_EQUAL(queriesCount, 1U); | |
86675669 OM |
1623 | } |
1624 | ||
42dcf516 OM |
1625 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig) |
1626 | { | |
86675669 OM |
1627 | std::unique_ptr<SyncRes> sr; |
1628 | initSR(sr, true); | |
1629 | ||
1630 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1631 | ||
1632 | primeHints(); | |
1633 | const DNSName target("."); | |
1634 | testkeysset_t keys; | |
1635 | ||
1636 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1637 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 | 1638 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); |
86675669 OM |
1639 | |
1640 | g_luaconfs.setState(luaconfsCopy); | |
c5f290df OM |
1641 | /* make sure that the signature inception and validity times are computed |
1642 | based on the SyncRes time, not the current one, in case the function | |
1643 | takes too long. */ | |
1644 | const time_t fixedNow = sr->getNow().tv_sec; | |
86675669 OM |
1645 | |
1646 | size_t queriesCount = 0; | |
1647 | ||
c0f8e484 | 1648 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 1649 | queriesCount++; |
86675669 | 1650 | |
42dcf516 | 1651 | if (domain == target && type == QType::NS) { |
86675669 | 1652 | |
42dcf516 OM |
1653 | setLWResult(res, 0, true, false, true); |
1654 | char addr[] = "a.root-servers.net."; | |
1655 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1656 | addr[0] = idx; | |
1657 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1658 | } | |
86675669 | 1659 | |
c5f290df | 1660 | addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow); |
86675669 | 1661 | |
42dcf516 OM |
1662 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
1663 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 1664 | |
308f4c43 | 1665 | return LWResult::Result::Success; |
42dcf516 | 1666 | } |
c0f8e484 | 1667 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 1668 | |
42dcf516 | 1669 | setLWResult(res, 0, true, false, true); |
86675669 | 1670 | |
42dcf516 | 1671 | addDNSKEY(keys, domain, 300, res->d_records); |
c5f290df | 1672 | addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow); |
86675669 | 1673 | |
308f4c43 | 1674 | return LWResult::Result::Success; |
42dcf516 | 1675 | } |
86675669 | 1676 | |
308f4c43 | 1677 | return LWResult::Result::Timeout; |
42dcf516 | 1678 | }); |
86675669 OM |
1679 | |
1680 | vector<DNSRecord> ret; | |
1681 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1682 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1683 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); |
86675669 | 1684 | /* 13 NS + 1 RRSIG */ |
690b86b7 OM |
1685 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1686 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
1687 | |
1688 | /* again, to test the cache */ | |
1689 | ret.clear(); | |
1690 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1691 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1692 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); |
690b86b7 OM |
1693 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1694 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
1695 | } |
1696 | ||
15e973d6 OM |
1697 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_sigs) |
1698 | { | |
1699 | std::unique_ptr<SyncRes> sr; | |
1700 | initSR(sr, true); | |
1701 | ||
1702 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1703 | ||
1704 | primeHints(); | |
1705 | const DNSName target("."); | |
1706 | testkeysset_t keys; | |
1707 | ||
1708 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1709 | luaconfsCopy.dsAnchors.clear(); | |
1710 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); | |
1711 | ||
1712 | g_luaconfs.setState(luaconfsCopy); | |
1713 | /* make sure that the signature inception and validity times are computed | |
1714 | based on the SyncRes time, not the current one, in case the function | |
1715 | takes too long. */ | |
1716 | const time_t fixedNow = sr->getNow().tv_sec; | |
1717 | ||
1718 | size_t queriesCount = 0; | |
1719 | ||
1720 | sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) { | |
1721 | queriesCount++; | |
1722 | ||
1723 | if (domain == target && type == QType::NS) { | |
1724 | ||
1725 | setLWResult(res, 0, true, false, true); | |
1726 | char addr[] = "a.root-servers.net."; | |
1727 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1728 | addr[0] = idx; | |
1729 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1730 | } | |
1731 | ||
1732 | addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow); | |
1733 | addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow); | |
1734 | addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow); | |
1735 | ||
1736 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
1737 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
1738 | ||
1739 | return LWResult::Result::Success; | |
1740 | } | |
1741 | else if (domain == target && type == QType::DNSKEY) { | |
1742 | ||
1743 | setLWResult(res, 0, true, false, true); | |
1744 | ||
1745 | addDNSKEY(keys, domain, 300, res->d_records); | |
1746 | addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow); | |
1747 | ||
1748 | return LWResult::Result::Success; | |
1749 | } | |
1750 | ||
1751 | return LWResult::Result::Timeout; | |
1752 | }); | |
1753 | ||
1754 | g_maxRRSIGsPerRecordToConsider = 2; | |
1755 | ||
1756 | vector<DNSRecord> ret; | |
1757 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1758 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1759 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); | |
1760 | /* 13 NS + 1 RRSIG */ | |
1761 | BOOST_REQUIRE_EQUAL(ret.size(), 16U); | |
1762 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1763 | ||
1764 | /* again, to test the cache */ | |
1765 | ret.clear(); | |
1766 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1767 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
1768 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); | |
1769 | BOOST_REQUIRE_EQUAL(ret.size(), 16U); | |
1770 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
1771 | ||
1772 | g_maxRRSIGsPerRecordToConsider = 0; | |
1773 | } | |
1774 | ||
1775 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_too_many_sig_validations) | |
1776 | { | |
1777 | std::unique_ptr<SyncRes> sr; | |
1778 | initSR(sr, true); | |
1779 | ||
1780 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1781 | ||
1782 | primeHints(); | |
1783 | const DNSName target("."); | |
1784 | testkeysset_t keys; | |
1785 | ||
1786 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1787 | luaconfsCopy.dsAnchors.clear(); | |
1788 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); | |
1789 | ||
1790 | g_luaconfs.setState(luaconfsCopy); | |
1791 | /* make sure that the signature inception and validity times are computed | |
1792 | based on the SyncRes time, not the current one, in case the function | |
1793 | takes too long. */ | |
1794 | const time_t fixedNow = sr->getNow().tv_sec; | |
1795 | ||
1796 | size_t queriesCount = 0; | |
1797 | ||
1798 | sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) { | |
1799 | queriesCount++; | |
1800 | ||
1801 | if (domain == target && type == QType::NS) { | |
1802 | ||
1803 | setLWResult(res, 0, true, false, true); | |
1804 | char addr[] = "a.root-servers.net."; | |
1805 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1806 | addr[0] = idx; | |
1807 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1808 | } | |
1809 | ||
1810 | addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow); | |
1811 | addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow); | |
1812 | ||
1813 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
1814 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
1815 | ||
1816 | return LWResult::Result::Success; | |
1817 | } | |
1818 | else if (domain == target && type == QType::DNSKEY) { | |
1819 | ||
1820 | setLWResult(res, 0, true, false, true); | |
1821 | ||
1822 | addDNSKEY(keys, domain, 300, res->d_records); | |
1823 | addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow); | |
1824 | ||
1825 | return LWResult::Result::Success; | |
1826 | } | |
1827 | ||
1828 | return LWResult::Result::Timeout; | |
1829 | }); | |
1830 | ||
1831 | SyncRes::s_maxvalidationsperq = 1U; | |
1832 | ||
1833 | vector<DNSRecord> ret; | |
1834 | BOOST_REQUIRE_THROW(sr->beginResolve(target, QType(QType::NS), QClass::IN, ret), ImmediateServFailException); | |
1835 | ||
1836 | SyncRes::s_maxvalidationsperq = 0U; | |
1837 | } | |
1838 | ||
42dcf516 OM |
1839 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo) |
1840 | { | |
86675669 OM |
1841 | std::unique_ptr<SyncRes> sr; |
1842 | initSR(sr, true); | |
1843 | ||
1844 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1845 | ||
1846 | primeHints(); | |
1847 | const DNSName target("."); | |
1848 | testkeysset_t keys; | |
1849 | ||
1850 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1851 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 | 1852 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); |
86675669 OM |
1853 | |
1854 | g_luaconfs.setState(luaconfsCopy); | |
1855 | ||
1856 | size_t queriesCount = 0; | |
1857 | ||
c0f8e484 | 1858 | sr->setAsyncCallback([&](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 1859 | queriesCount++; |
86675669 | 1860 | |
42dcf516 | 1861 | if (domain == target && type == QType::NS) { |
86675669 | 1862 | |
42dcf516 OM |
1863 | setLWResult(res, 0, true, false, true); |
1864 | char addr[] = "a.root-servers.net."; | |
1865 | for (char idx = 'a'; idx <= 'm'; idx++) { | |
1866 | addr[0] = idx; | |
1867 | addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600); | |
1868 | } | |
86675669 | 1869 | |
42dcf516 OM |
1870 | /* FORCE WRONG ALGO */ |
1871 | addRRSIG(keys, res->d_records, domain, 300, false, DNSSECKeeper::RSASHA256); | |
86675669 | 1872 | |
42dcf516 OM |
1873 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); |
1874 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
86675669 | 1875 | |
308f4c43 | 1876 | return LWResult::Result::Success; |
42dcf516 | 1877 | } |
c0f8e484 | 1878 | if (domain == target && type == QType::DNSKEY) { |
86675669 | 1879 | |
42dcf516 | 1880 | setLWResult(res, 0, true, false, true); |
86675669 | 1881 | |
42dcf516 OM |
1882 | addDNSKEY(keys, domain, 300, res->d_records); |
1883 | addRRSIG(keys, res->d_records, domain, 300); | |
86675669 | 1884 | |
308f4c43 | 1885 | return LWResult::Result::Success; |
42dcf516 | 1886 | } |
86675669 | 1887 | |
308f4c43 | 1888 | return LWResult::Result::Timeout; |
42dcf516 | 1889 | }); |
86675669 OM |
1890 | |
1891 | vector<DNSRecord> ret; | |
1892 | int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1893 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1894 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); |
86675669 | 1895 | /* 13 NS + 1 RRSIG */ |
690b86b7 OM |
1896 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1897 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
1898 | |
1899 | /* again, to test the cache */ | |
1900 | ret.clear(); | |
1901 | res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); | |
1902 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1903 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG); |
690b86b7 OM |
1904 | BOOST_REQUIRE_EQUAL(ret.size(), 14U); |
1905 | BOOST_CHECK_EQUAL(queriesCount, 2U); | |
86675669 OM |
1906 | } |
1907 | ||
42dcf516 OM |
1908 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds) |
1909 | { | |
86675669 OM |
1910 | std::unique_ptr<SyncRes> sr; |
1911 | initSR(sr, true); | |
1912 | ||
1913 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1914 | ||
1915 | primeHints(); | |
1916 | const DNSName target("com."); | |
1917 | const ComboAddress targetAddr("192.0.2.42"); | |
1918 | testkeysset_t keys; | |
1919 | ||
1920 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
1921 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 OM |
1922 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); |
1923 | generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys); | |
86675669 OM |
1924 | |
1925 | g_luaconfs.setState(luaconfsCopy); | |
1926 | ||
1927 | size_t queriesCount = 0; | |
1928 | ||
c0f8e484 | 1929 | sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 1930 | queriesCount++; |
86675669 | 1931 | |
42dcf516 | 1932 | DNSName auth = domain; |
86675669 | 1933 | |
42dcf516 | 1934 | if (type == QType::DS || type == QType::DNSKEY) { |
308f4c43 RG |
1935 | if (genericDSAndDNSKEYHandler(res, domain, auth, type, keys) == LWResult::Result::Timeout) { |
1936 | return LWResult::Result::Timeout; | |
86675669 OM |
1937 | } |
1938 | ||
42dcf516 OM |
1939 | if (type == QType::DS && domain == target) { |
1940 | /* remove the last record, which is the DS's RRSIG */ | |
1941 | res->d_records.pop_back(); | |
86675669 OM |
1942 | } |
1943 | ||
308f4c43 | 1944 | return LWResult::Result::Success; |
42dcf516 OM |
1945 | } |
1946 | ||
c0f8e484 | 1947 | if (isRootServer(address)) { |
42dcf516 OM |
1948 | setLWResult(res, 0, false, false, true); |
1949 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600); | |
1950 | /* Include the DS but omit the RRSIG*/ | |
1951 | addDS(DNSName("com."), 300, res->d_records, keys); | |
1952 | addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
308f4c43 | 1953 | return LWResult::Result::Success; |
42dcf516 | 1954 | } |
86675669 | 1955 | |
c0f8e484 | 1956 | if (address == ComboAddress("192.0.2.1:53")) { |
42dcf516 OM |
1957 | setLWResult(res, RCode::NoError, true, false, true); |
1958 | addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600); | |
1959 | addRRSIG(keys, res->d_records, auth, 300); | |
308f4c43 | 1960 | return LWResult::Result::Success; |
42dcf516 OM |
1961 | } |
1962 | ||
308f4c43 | 1963 | return LWResult::Result::Timeout; |
42dcf516 | 1964 | }); |
86675669 OM |
1965 | |
1966 | vector<DNSRecord> ret; | |
1967 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1968 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1969 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); |
690b86b7 OM |
1970 | BOOST_REQUIRE_EQUAL(ret.size(), 2U); |
1971 | BOOST_CHECK_EQUAL(queriesCount, 3U); | |
86675669 OM |
1972 | |
1973 | /* again, to test the cache */ | |
1974 | ret.clear(); | |
1975 | res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1976 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1977 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); |
690b86b7 OM |
1978 | BOOST_REQUIRE_EQUAL(ret.size(), 2U); |
1979 | BOOST_CHECK_EQUAL(queriesCount, 3U); | |
86675669 OM |
1980 | |
1981 | /* now we ask directly for the DS */ | |
1982 | ret.clear(); | |
1983 | res = sr->beginResolve(DNSName("com."), QType(QType::DS), QClass::IN, ret); | |
1984 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 1985 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); |
690b86b7 OM |
1986 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
1987 | BOOST_CHECK_EQUAL(queriesCount, 3U); | |
86675669 OM |
1988 | } |
1989 | ||
42dcf516 OM |
1990 | BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds_direct) |
1991 | { | |
86675669 OM |
1992 | std::unique_ptr<SyncRes> sr; |
1993 | initSR(sr, true); | |
1994 | ||
1995 | setDNSSECValidation(sr, DNSSECMode::ValidateAll); | |
1996 | ||
1997 | primeHints(); | |
1998 | const DNSName target("com."); | |
1999 | testkeysset_t keys; | |
2000 | ||
2001 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
2002 | luaconfsCopy.dsAnchors.clear(); | |
690b86b7 OM |
2003 | generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors); |
2004 | generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys); | |
86675669 OM |
2005 | |
2006 | g_luaconfs.setState(luaconfsCopy); | |
2007 | ||
2008 | size_t queriesCount = 0; | |
2009 | ||
c0f8e484 | 2010 | sr->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { |
42dcf516 | 2011 | queriesCount++; |
86675669 | 2012 | |
42dcf516 | 2013 | DNSName auth = domain; |
86675669 | 2014 | |
42dcf516 | 2015 | if (type == QType::DS || type == QType::DNSKEY) { |
308f4c43 RG |
2016 | if (genericDSAndDNSKEYHandler(res, domain, auth, type, keys) == LWResult::Result::Timeout) { |
2017 | return LWResult::Result::Timeout; | |
86675669 OM |
2018 | } |
2019 | ||
42dcf516 OM |
2020 | if (type == QType::DS && domain == target) { |
2021 | /* remove the last record, which is the DS's RRSIG */ | |
2022 | res->d_records.pop_back(); | |
86675669 OM |
2023 | } |
2024 | ||
308f4c43 | 2025 | return LWResult::Result::Success; |
42dcf516 OM |
2026 | } |
2027 | ||
c0f8e484 | 2028 | if (isRootServer(address)) { |
42dcf516 OM |
2029 | setLWResult(res, 0, false, false, true); |
2030 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600); | |
2031 | /* Include the DS but omit the RRSIG*/ | |
2032 | addDS(DNSName("com."), 300, res->d_records, keys); | |
2033 | addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
308f4c43 | 2034 | return LWResult::Result::Success; |
42dcf516 OM |
2035 | } |
2036 | ||
308f4c43 | 2037 | return LWResult::Result::Timeout; |
42dcf516 | 2038 | }); |
86675669 OM |
2039 | |
2040 | vector<DNSRecord> ret; | |
2041 | int res = sr->beginResolve(DNSName("com."), QType(QType::DS), QClass::IN, ret); | |
2042 | BOOST_CHECK_EQUAL(res, RCode::NoError); | |
fd870915 | 2043 | BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); |
690b86b7 OM |
2044 | BOOST_REQUIRE_EQUAL(ret.size(), 1U); |
2045 | BOOST_CHECK_EQUAL(queriesCount, 1U); | |
86675669 OM |
2046 | } |
2047 | ||
2048 | BOOST_AUTO_TEST_SUITE_END() |