]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/test-syncres_cc4.cc
updated KSK and ZSK Rollover procedures, small fixes in Algorithm Rollover procedure
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc4.cc
1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
3
4 #include "test-syncres_cc.hh"
5
6 BOOST_AUTO_TEST_SUITE(syncres_cc4)
7
8 BOOST_AUTO_TEST_CASE(test_auth_zone_nodata)
9 {
10 std::unique_ptr<SyncRes> sr;
11 initSR(sr);
12
13 primeHints();
14
15 size_t queriesCount = 0;
16 const DNSName target("nodata.powerdns.com.");
17 const DNSName authZone("powerdns.com");
18
19 SyncRes::AuthDomain ad;
20 ad.d_name = authZone;
21 DNSRecord dr;
22 dr.d_place = DNSResourceRecord::ANSWER;
23 dr.d_name = target;
24 dr.d_type = QType::A;
25 dr.d_ttl = 3600;
26 dr.d_content = std::make_shared<ARecordContent>(ComboAddress("192.0.2.1"));
27 ad.d_records.insert(dr);
28
29 dr.d_place = DNSResourceRecord::ANSWER;
30 dr.d_name = authZone;
31 dr.d_type = QType::SOA;
32 dr.d_ttl = 3600;
33 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
34 ad.d_records.insert(dr);
35
36 auto map = std::make_shared<SyncRes::domainmap_t>();
37 (*map)[authZone] = ad;
38 SyncRes::setDomainMap(map);
39
40 sr->setAsyncCallback([&queriesCount](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) {
41 queriesCount++;
42
43 return LWResult::Result::Timeout;
44 });
45
46 vector<DNSRecord> ret;
47 int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
48 BOOST_CHECK_EQUAL(res, RCode::NoError);
49 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
50 BOOST_CHECK(ret[0].d_type == QType::SOA);
51 BOOST_CHECK_EQUAL(queriesCount, 0U);
52 }
53
54 BOOST_AUTO_TEST_CASE(test_auth_zone_nx)
55 {
56 std::unique_ptr<SyncRes> sr;
57 initSR(sr);
58
59 primeHints();
60
61 size_t queriesCount = 0;
62 const DNSName target("nx.powerdns.com.");
63 const DNSName authZone("powerdns.com");
64
65 SyncRes::AuthDomain ad;
66 ad.d_name = authZone;
67 DNSRecord dr;
68 dr.d_place = DNSResourceRecord::ANSWER;
69 dr.d_name = DNSName("powerdns.com.");
70 dr.d_type = QType::SOA;
71 dr.d_ttl = 3600;
72 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
73 ad.d_records.insert(dr);
74
75 auto map = std::make_shared<SyncRes::domainmap_t>();
76 (*map)[authZone] = ad;
77 SyncRes::setDomainMap(map);
78
79 sr->setAsyncCallback([&queriesCount](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) {
80 queriesCount++;
81
82 return LWResult::Result::Timeout;
83 });
84
85 vector<DNSRecord> ret;
86 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
87 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
88 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
89 BOOST_CHECK(ret[0].d_type == QType::SOA);
90 BOOST_CHECK_EQUAL(queriesCount, 0U);
91 }
92
93 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation)
94 {
95 std::unique_ptr<SyncRes> sr;
96 initSR(sr, true);
97
98 primeHints();
99
100 size_t queriesCount = 0;
101 const DNSName target("www.test.powerdns.com.");
102 const ComboAddress targetAddr("192.0.2.2");
103 const DNSName ns("ns1.test.powerdns.com.");
104 const ComboAddress nsAddr("192.0.2.1");
105 const DNSName authZone("powerdns.com");
106
107 SyncRes::AuthDomain ad;
108 ad.d_name = authZone;
109 DNSRecord dr;
110 dr.d_place = DNSResourceRecord::ANSWER;
111 dr.d_name = authZone;
112 dr.d_type = QType::SOA;
113 dr.d_ttl = 3600;
114 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
115 ad.d_records.insert(dr);
116
117 dr.d_place = DNSResourceRecord::ANSWER;
118 dr.d_name = DNSName("test.powerdns.com.");
119 dr.d_type = QType::NS;
120 dr.d_ttl = 3600;
121 dr.d_content = std::make_shared<NSRecordContent>(ns);
122 ad.d_records.insert(dr);
123
124 dr.d_place = DNSResourceRecord::ANSWER;
125 dr.d_name = ns;
126 dr.d_type = QType::A;
127 dr.d_ttl = 3600;
128 dr.d_content = std::make_shared<ARecordContent>(nsAddr);
129 ad.d_records.insert(dr);
130
131 auto map = std::make_shared<SyncRes::domainmap_t>();
132 (*map)[authZone] = ad;
133 SyncRes::setDomainMap(map);
134
135 testkeysset_t keys;
136 auto luaconfsCopy = g_luaconfs.getCopy();
137 luaconfsCopy.dsAnchors.clear();
138 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
139 g_luaconfs.setState(luaconfsCopy);
140
141 /* make sure that the signature inception and validity times are computed
142 based on the SyncRes time, not the current one, in case the function
143 takes too long. */
144 const time_t fixedNow = sr->getNow().tv_sec;
145
146 sr->setAsyncCallback([&queriesCount, target, targetAddr, nsAddr, authZone, 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) {
147 queriesCount++;
148 if (type == QType::DS || type == QType::DNSKEY) {
149 return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys, domain == DNSName("com.") || domain == authZone, fixedNow);
150 }
151
152 if (ip == ComboAddress(nsAddr.toString(), 53) && domain == target) {
153 setLWResult(res, 0, true, false, true);
154 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
155 return LWResult::Result::Success;
156 }
157
158 return LWResult::Result::Timeout;
159 });
160
161 sr->setDNSSECValidationRequested(true);
162 vector<DNSRecord> ret;
163 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
164 BOOST_CHECK_EQUAL(res, RCode::NoError);
165 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
166 BOOST_CHECK(ret[0].d_type == QType::A);
167 BOOST_CHECK_EQUAL(queriesCount, 1U);
168 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
169 }
170
171 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point)
172 {
173 std::unique_ptr<SyncRes> sr;
174 initSR(sr);
175
176 primeHints();
177
178 size_t queriesCount = 0;
179 const DNSName target("test.powerdns.com.");
180 const ComboAddress targetAddr("192.0.2.2");
181 const DNSName ns("ns1.test.powerdns.com.");
182 const ComboAddress nsAddr("192.0.2.1");
183 const DNSName authZone("powerdns.com");
184
185 SyncRes::AuthDomain ad;
186 ad.d_name = authZone;
187 DNSRecord dr;
188 dr.d_place = DNSResourceRecord::ANSWER;
189 dr.d_name = authZone;
190 dr.d_type = QType::SOA;
191 dr.d_ttl = 3600;
192 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
193 ad.d_records.insert(dr);
194
195 dr.d_place = DNSResourceRecord::ANSWER;
196 dr.d_name = DNSName("test.powerdns.com.");
197 dr.d_type = QType::NS;
198 dr.d_ttl = 3600;
199 dr.d_content = std::make_shared<NSRecordContent>(ns);
200 ad.d_records.insert(dr);
201
202 dr.d_place = DNSResourceRecord::ANSWER;
203 dr.d_name = ns;
204 dr.d_type = QType::A;
205 dr.d_ttl = 3600;
206 dr.d_content = std::make_shared<ARecordContent>(nsAddr);
207 ad.d_records.insert(dr);
208
209 auto map = std::make_shared<SyncRes::domainmap_t>();
210 (*map)[authZone] = ad;
211 SyncRes::setDomainMap(map);
212
213 sr->setAsyncCallback([&queriesCount, nsAddr, target, targetAddr](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) {
214 queriesCount++;
215
216 if (ip == ComboAddress(nsAddr.toString(), 53) && domain == target) {
217 setLWResult(res, 0, true, false, true);
218 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
219 return LWResult::Result::Success;
220 }
221
222 return LWResult::Result::Timeout;
223 });
224
225 vector<DNSRecord> ret;
226 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
227 BOOST_CHECK_EQUAL(res, RCode::NoError);
228 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
229 BOOST_CHECK(ret[0].d_type == QType::A);
230 BOOST_CHECK_EQUAL(queriesCount, 1U);
231 }
232
233 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard)
234 {
235 std::unique_ptr<SyncRes> sr;
236 initSR(sr);
237
238 primeHints();
239
240 size_t queriesCount = 0;
241 const DNSName target("test.powerdns.com.");
242 const ComboAddress targetAddr("192.0.2.2");
243 const DNSName authZone("powerdns.com");
244
245 SyncRes::AuthDomain ad;
246 ad.d_name = authZone;
247 DNSRecord dr;
248 dr.d_place = DNSResourceRecord::ANSWER;
249 dr.d_name = authZone;
250 dr.d_type = QType::SOA;
251 dr.d_ttl = 3600;
252 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
253 ad.d_records.insert(dr);
254
255 dr.d_place = DNSResourceRecord::ANSWER;
256 dr.d_name = DNSName("*.powerdns.com.");
257 dr.d_type = QType::A;
258 dr.d_ttl = 3600;
259 dr.d_content = std::make_shared<ARecordContent>(targetAddr);
260 ad.d_records.insert(dr);
261
262 auto map = std::make_shared<SyncRes::domainmap_t>();
263 (*map)[authZone] = ad;
264 SyncRes::setDomainMap(map);
265
266 sr->setAsyncCallback([&queriesCount](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) {
267 queriesCount++;
268
269 return LWResult::Result::Timeout;
270 });
271
272 vector<DNSRecord> ret;
273 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
274 BOOST_CHECK_EQUAL(res, RCode::NoError);
275 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
276 BOOST_CHECK(ret[0].d_type == QType::A);
277 BOOST_CHECK_EQUAL(queriesCount, 0U);
278 }
279
280 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_with_ent)
281 {
282 std::unique_ptr<SyncRes> sr;
283 initSR(sr);
284
285 primeHints();
286
287 size_t queriesCount = 0;
288 const DNSName target("test.powerdns.com.");
289 const ComboAddress targetAddr1("192.0.2.1");
290 const ComboAddress targetAddr2("192.0.2.2");
291 const DNSName authZone("powerdns.com");
292
293 SyncRes::AuthDomain ad;
294 ad.d_name = authZone;
295 DNSRecord dr;
296 dr.d_place = DNSResourceRecord::ANSWER;
297 dr.d_name = authZone;
298 dr.d_type = QType::SOA;
299 dr.d_ttl = 3600;
300 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
301 ad.d_records.insert(dr);
302
303 dr.d_place = DNSResourceRecord::ANSWER;
304 dr.d_name = DNSName("abc.xyz.test.powerdns.com.");
305 dr.d_type = QType::A;
306 dr.d_ttl = 3600;
307 dr.d_content = std::make_shared<ARecordContent>(targetAddr1);
308 ad.d_records.insert(dr);
309
310 dr.d_place = DNSResourceRecord::ANSWER;
311 dr.d_name = DNSName("*.powerdns.com.");
312 dr.d_type = QType::A;
313 dr.d_ttl = 3600;
314 dr.d_content = std::make_shared<ARecordContent>(targetAddr2);
315 ad.d_records.insert(dr);
316
317 auto map = std::make_shared<SyncRes::domainmap_t>();
318 (*map)[authZone] = ad;
319 SyncRes::setDomainMap(map);
320
321 sr->setAsyncCallback([&queriesCount](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) {
322 queriesCount++;
323
324 return LWResult::Result::Timeout;
325 });
326
327 vector<DNSRecord> ret;
328 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
329 BOOST_CHECK_EQUAL(res, RCode::NoError);
330 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
331
332 // WARN below should be changed to CHECK once the issue is fixed.
333 const string m("Please fix issue #8312");
334 BOOST_WARN_MESSAGE(ret[0].d_type == QType::SOA, m);
335 BOOST_CHECK_EQUAL(queriesCount, 0U);
336 }
337
338 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata)
339 {
340 std::unique_ptr<SyncRes> sr;
341 initSR(sr);
342
343 primeHints();
344
345 size_t queriesCount = 0;
346 const DNSName target("test.powerdns.com.");
347 const ComboAddress targetAddr("192.0.2.2");
348 const DNSName authZone("powerdns.com");
349
350 SyncRes::AuthDomain ad;
351 ad.d_name = authZone;
352 DNSRecord dr;
353 dr.d_place = DNSResourceRecord::ANSWER;
354 dr.d_name = authZone;
355 dr.d_type = QType::SOA;
356 dr.d_ttl = 3600;
357 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
358 ad.d_records.insert(dr);
359
360 dr.d_place = DNSResourceRecord::ANSWER;
361 dr.d_name = DNSName("*.powerdns.com.");
362 dr.d_type = QType::A;
363 dr.d_ttl = 3600;
364 dr.d_content = std::make_shared<ARecordContent>(targetAddr);
365 ad.d_records.insert(dr);
366
367 auto map = std::make_shared<SyncRes::domainmap_t>();
368 (*map)[authZone] = ad;
369 SyncRes::setDomainMap(map);
370
371 sr->setAsyncCallback([&queriesCount](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) {
372 queriesCount++;
373
374 return LWResult::Result::Timeout;
375 });
376
377 vector<DNSRecord> ret;
378 int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
379 BOOST_CHECK_EQUAL(res, RCode::NoError);
380 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
381 BOOST_CHECK(ret[0].d_type == QType::SOA);
382 BOOST_CHECK_EQUAL(queriesCount, 0U);
383 }
384
385 BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only)
386 {
387 std::unique_ptr<SyncRes> sr;
388 initSR(sr);
389
390 primeHints();
391
392 size_t queriesCount = 0;
393 const DNSName target("powerdns.com.");
394 const ComboAddress addr("192.0.2.5");
395
396 SyncRes::AuthDomain ad;
397 ad.d_name = target;
398 DNSRecord dr;
399 dr.d_place = DNSResourceRecord::ANSWER;
400 dr.d_name = target;
401 dr.d_type = QType::SOA;
402 dr.d_ttl = 3600;
403 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
404 ad.d_records.insert(dr);
405
406 dr.d_place = DNSResourceRecord::ANSWER;
407 dr.d_name = target;
408 dr.d_type = QType::A;
409 dr.d_ttl = 3600;
410 dr.d_content = std::make_shared<ARecordContent>(addr);
411 ad.d_records.insert(dr);
412
413 auto map = std::make_shared<SyncRes::domainmap_t>();
414 (*map)[target] = ad;
415 SyncRes::setDomainMap(map);
416
417 sr->setAsyncCallback([&queriesCount](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) {
418 queriesCount++;
419 setLWResult(res, 0, true, false, true);
420 addRecordToLW(res, domain, QType::A, "192.0.2.42");
421 return LWResult::Result::Success;
422 });
423
424 /* simulate a no-RD query */
425 sr->setCacheOnly();
426
427 vector<DNSRecord> ret;
428 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
429 BOOST_CHECK_EQUAL(res, RCode::NoError);
430 BOOST_CHECK_EQUAL(ret.size(), 1U);
431 BOOST_CHECK(ret[0].d_type == QType::A);
432 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
433 BOOST_CHECK_EQUAL(queriesCount, 0U);
434 }
435
436 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig)
437 {
438 initSR();
439
440 auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
441 dcke->create(dcke->getBits());
442 // cerr<<dcke->convertToISC()<<endl;
443 DNSSECPrivateKey dpk;
444 dpk.d_flags = 256;
445 dpk.setKey(std::move(dcke));
446
447 sortedRecords_t recordcontents;
448 recordcontents.insert(getRecordContent(QType::A, "192.0.2.1"));
449
450 DNSName qname("powerdns.com.");
451
452 time_t now = time(nullptr);
453 RRSIGRecordContent rrc;
454 /* this RRSIG is valid for the current second only */
455 computeRRSIG(dpk, qname, qname, QType::A, 600, 0, rrc, recordcontents, boost::none, now);
456
457 skeyset_t keyset;
458 keyset.insert(std::make_shared<DNSKEYRecordContent>(dpk.getDNSKEY()));
459
460 std::vector<std::shared_ptr<RRSIGRecordContent>> sigs;
461 sigs.push_back(std::make_shared<RRSIGRecordContent>(rrc));
462
463 BOOST_CHECK(validateWithKeySet(now, qname, recordcontents, sigs, keyset) == vState::Secure);
464 }
465
466 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk)
467 {
468 std::unique_ptr<SyncRes> sr;
469 initSR(sr, true);
470
471 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
472
473 primeHints();
474 const DNSName target(".");
475 testkeysset_t keys;
476
477 auto luaconfsCopy = g_luaconfs.getCopy();
478 luaconfsCopy.dsAnchors.clear();
479 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
480 g_luaconfs.setState(luaconfsCopy);
481
482 size_t queriesCount = 0;
483
484 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) {
485 queriesCount++;
486
487 if (domain == target && type == QType::NS) {
488
489 setLWResult(res, 0, true, false, true);
490 char addr[] = "a.root-servers.net.";
491 for (char idx = 'a'; idx <= 'm'; idx++) {
492 addr[0] = idx;
493 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
494 }
495
496 addRRSIG(keys, res->d_records, domain, 300);
497
498 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
499 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
500
501 return LWResult::Result::Success;
502 }
503 else if (domain == target && type == QType::DNSKEY) {
504
505 setLWResult(res, 0, true, false, true);
506
507 addDNSKEY(keys, domain, 300, res->d_records);
508 addRRSIG(keys, res->d_records, domain, 300);
509
510 return LWResult::Result::Success;
511 }
512
513 return LWResult::Result::Timeout;
514 });
515
516 vector<DNSRecord> ret;
517 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
518 BOOST_CHECK_EQUAL(res, RCode::NoError);
519 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
520 /* 13 NS + 1 RRSIG */
521 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
522 BOOST_CHECK_EQUAL(queriesCount, 2U);
523
524 /* again, to test the cache */
525 ret.clear();
526 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
527 BOOST_CHECK_EQUAL(res, RCode::NoError);
528 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
529 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
530 BOOST_CHECK_EQUAL(queriesCount, 2U);
531 }
532
533 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk)
534 {
535 std::unique_ptr<SyncRes> sr;
536 initSR(sr, true);
537
538 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
539
540 primeHints();
541 const DNSName target(".");
542 testkeysset_t zskeys;
543 testkeysset_t kskeys;
544
545 /* Generate key material for "." */
546 auto dckeZ = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
547 dckeZ->create(dckeZ->getBits());
548 DNSSECPrivateKey ksk;
549 ksk.d_flags = 257;
550 ksk.setKey(std::move(dckeZ));
551 DSRecordContent kskds = makeDSFromDNSKey(target, ksk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
552
553 auto dckeK = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
554 dckeK->create(dckeK->getBits());
555 DNSSECPrivateKey zsk;
556 zsk.d_flags = 256;
557 zsk.setKey(std::move(dckeK));
558 DSRecordContent zskds = makeDSFromDNSKey(target, zsk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
559
560 kskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(ksk, kskds);
561 zskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(zsk, zskds);
562
563 /* Set the root DS */
564 auto luaconfsCopy = g_luaconfs.getCopy();
565 luaconfsCopy.dsAnchors.clear();
566 luaconfsCopy.dsAnchors[g_rootdnsname].insert(kskds);
567 g_luaconfs.setState(luaconfsCopy);
568
569 size_t queriesCount = 0;
570
571 sr->setAsyncCallback([target, &queriesCount, zskeys, kskeys](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) {
572 queriesCount++;
573
574 if (domain == target && type == QType::NS) {
575
576 setLWResult(res, 0, true, false, true);
577 char addr[] = "a.root-servers.net.";
578 for (char idx = 'a'; idx <= 'm'; idx++) {
579 addr[0] = idx;
580 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
581 }
582
583 addRRSIG(zskeys, res->d_records, domain, 300);
584
585 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
586 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
587
588 return LWResult::Result::Success;
589 }
590 else if (domain == target && type == QType::DNSKEY) {
591
592 setLWResult(res, 0, true, false, true);
593
594 addDNSKEY(kskeys, domain, 300, res->d_records);
595 addDNSKEY(zskeys, domain, 300, res->d_records);
596 addRRSIG(kskeys, res->d_records, domain, 300);
597
598 return LWResult::Result::Success;
599 }
600
601 return LWResult::Result::Timeout;
602 });
603
604 vector<DNSRecord> ret;
605 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
606 BOOST_CHECK_EQUAL(res, RCode::NoError);
607 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
608 /* 13 NS + 1 RRSIG */
609 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
610 BOOST_CHECK_EQUAL(queriesCount, 2U);
611
612 /* again, to test the cache */
613 ret.clear();
614 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
615 BOOST_CHECK_EQUAL(res, RCode::NoError);
616 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
617 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
618 BOOST_CHECK_EQUAL(queriesCount, 2U);
619 }
620
621 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey)
622 {
623 std::unique_ptr<SyncRes> sr;
624 initSR(sr, true);
625
626 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
627
628 primeHints();
629 const DNSName target(".");
630 testkeysset_t keys;
631
632 auto luaconfsCopy = g_luaconfs.getCopy();
633 luaconfsCopy.dsAnchors.clear();
634 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
635 g_luaconfs.setState(luaconfsCopy);
636
637 size_t queriesCount = 0;
638
639 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) {
640 queriesCount++;
641
642 if (domain == target && type == QType::NS) {
643
644 setLWResult(res, 0, true, false, true);
645 char addr[] = "a.root-servers.net.";
646 for (char idx = 'a'; idx <= 'm'; idx++) {
647 addr[0] = idx;
648 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
649 }
650
651 addRRSIG(keys, res->d_records, domain, 300);
652
653 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
654 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
655
656 return LWResult::Result::Success;
657 }
658 else if (domain == target && type == QType::DNSKEY) {
659
660 setLWResult(res, 0, true, false, true);
661
662 /* No DNSKEY */
663
664 return LWResult::Result::Success;
665 }
666
667 return LWResult::Result::Timeout;
668 });
669
670 vector<DNSRecord> ret;
671 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
672 BOOST_CHECK_EQUAL(res, RCode::NoError);
673 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
674 /* 13 NS + 1 RRSIG */
675 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
676 BOOST_CHECK_EQUAL(queriesCount, 2U);
677
678 /* again, to test the cache */
679 ret.clear();
680 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
681 BOOST_CHECK_EQUAL(res, RCode::NoError);
682 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
683 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
684 BOOST_CHECK_EQUAL(queriesCount, 2U);
685 }
686
687 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_without_zone_flag)
688 {
689 std::unique_ptr<SyncRes> sr;
690 initSR(sr, true);
691
692 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
693
694 primeHints();
695 const DNSName target(".");
696 testkeysset_t keys;
697
698 /* Generate key material for "." */
699 auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
700 dcke->create(dcke->getBits());
701 DNSSECPrivateKey csk;
702 csk.d_flags = 0;
703 csk.setKey(std::move(dcke));
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
716 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) {
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
732 return LWResult::Result::Success;
733 }
734 else if (domain == target && type == QType::DNSKEY) {
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
741 return LWResult::Result::Success;
742 }
743
744 return LWResult::Result::Timeout;
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);
750 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoZoneKeyBitSet);
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);
759 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoZoneKeyBitSet);
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 "." */
776 auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
777 dcke->create(dcke->getBits());
778 DNSSECPrivateKey csk;
779 csk.d_flags = 257 | 128;
780 csk.setKey(std::move(dcke));
781 DSRecordContent ds = makeDSFromDNSKey(target, csk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
782
783 keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(csk, ds);
784
785 /* Set the root DS */
786 auto luaconfsCopy = g_luaconfs.getCopy();
787 luaconfsCopy.dsAnchors.clear();
788 luaconfsCopy.dsAnchors[g_rootdnsname].insert(ds);
789 g_luaconfs.setState(luaconfsCopy);
790
791 size_t queriesCount = 0;
792
793 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) {
794 queriesCount++;
795
796 if (domain == target && type == QType::NS) {
797
798 setLWResult(res, 0, true, false, true);
799 char addr[] = "a.root-servers.net.";
800 for (char idx = 'a'; idx <= 'm'; idx++) {
801 addr[0] = idx;
802 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
803 }
804
805 addRRSIG(keys, res->d_records, domain, 300);
806 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
807 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
808
809 return LWResult::Result::Success;
810 }
811 else if (domain == target && type == QType::DNSKEY) {
812
813 setLWResult(res, 0, true, false, true);
814
815 addDNSKEY(keys, domain, 300, res->d_records);
816 addRRSIG(keys, res->d_records, domain, 300);
817
818 return LWResult::Result::Success;
819 }
820
821 return LWResult::Result::Timeout;
822 });
823
824 vector<DNSRecord> ret;
825 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
826 BOOST_CHECK_EQUAL(res, RCode::NoError);
827 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusRevokedDNSKEY);
828 /* 13 NS + 1 RRSIG */
829 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
830 BOOST_CHECK_EQUAL(queriesCount, 2U);
831
832 /* again, to test the cache */
833 ret.clear();
834 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
835 BOOST_CHECK_EQUAL(res, RCode::NoError);
836 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusRevokedDNSKEY);
837 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
838 BOOST_CHECK_EQUAL(queriesCount, 2U);
839 }
840 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds)
841 {
842 std::unique_ptr<SyncRes> sr;
843 initSR(sr, true);
844
845 setDNSSECValidation(sr, DNSSECMode::Process);
846
847 primeHints();
848 const DNSName target(".");
849 testkeysset_t dskeys;
850 testkeysset_t keys;
851
852 /* Generate key material for "." */
853 auto dckeDS = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
854 dckeDS->create(dckeDS->getBits());
855 DNSSECPrivateKey dskey;
856 dskey.d_flags = 257;
857 dskey.setKey(std::move(dckeDS));
858 DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
859
860 auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
861 dcke->create(dcke->getBits());
862 DNSSECPrivateKey dpk;
863 dpk.d_flags = 256;
864 dpk.setKey(std::move(dcke));
865 DSRecordContent uselessdrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
866
867 dskeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dskey, drc);
868 keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, uselessdrc);
869
870 /* Set the root DS */
871 auto luaconfsCopy = g_luaconfs.getCopy();
872 luaconfsCopy.dsAnchors.clear();
873 luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
874 g_luaconfs.setState(luaconfsCopy);
875
876 size_t queriesCount = 0;
877
878 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) {
879 queriesCount++;
880
881 if (domain == target && type == QType::NS) {
882
883 setLWResult(res, 0, true, false, true);
884 char addr[] = "a.root-servers.net.";
885 for (char idx = 'a'; idx <= 'm'; idx++) {
886 addr[0] = idx;
887 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
888 }
889
890 addRRSIG(keys, res->d_records, domain, 300);
891
892 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
893 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
894
895 return LWResult::Result::Success;
896 }
897 else if (domain == target && type == QType::DNSKEY) {
898
899 setLWResult(res, 0, true, false, true);
900
901 addDNSKEY(keys, domain, 300, res->d_records);
902 addRRSIG(keys, res->d_records, domain, 300);
903
904 return LWResult::Result::Success;
905 }
906
907 return LWResult::Result::Timeout;
908 });
909
910 /* === with validation enabled === */
911 sr->setDNSSECValidationRequested(true);
912 vector<DNSRecord> ret;
913 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
914 BOOST_CHECK_EQUAL(res, RCode::NoError);
915 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
916 /* 13 NS + 1 RRSIG */
917 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
918 BOOST_CHECK_EQUAL(queriesCount, 2U);
919
920 /* again, to test the cache */
921 ret.clear();
922 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
923 BOOST_CHECK_EQUAL(res, RCode::NoError);
924 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
925 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
926 BOOST_CHECK_EQUAL(queriesCount, 2U);
927
928 /* === first without validation, then with (just-in-time validation) === */
929 /* clear the caches */
930 g_recCache = std::make_unique<MemRecursorCache>();
931 g_negCache = std::make_unique<NegCache>();
932 sr->setDNSSECValidationRequested(false);
933 primeHints();
934
935 ret.clear();
936 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
937 BOOST_CHECK_EQUAL(res, RCode::NoError);
938 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
939 /* 13 NS + 1 RRSIG */
940 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
941 BOOST_CHECK_EQUAL(queriesCount, 3U);
942
943 /* now we ask for the DNSKEYs (still without validation) */
944 ret.clear();
945 res = sr->beginResolve(target, QType(QType::DNSKEY), QClass::IN, ret);
946 BOOST_CHECK_EQUAL(res, RCode::NoError);
947 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
948 /* 1 SOA + 1 RRSIG */
949 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
950 BOOST_CHECK_EQUAL(queriesCount, 4U);
951
952 /* again, to test the cache WITH validation */
953 sr->setDNSSECValidationRequested(true);
954 ret.clear();
955 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
956 BOOST_CHECK_EQUAL(res, RCode::NoError);
957 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidDNSKEY);
958 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
959 BOOST_CHECK_EQUAL(queriesCount, 4U);
960 }
961
962 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey)
963 {
964 std::unique_ptr<SyncRes> sr;
965 initSR(sr, true);
966
967 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
968
969 primeHints();
970 const DNSName target(".");
971 testkeysset_t keys;
972 testkeysset_t rrsigkeys;
973
974 auto luaconfsCopy = g_luaconfs.getCopy();
975 luaconfsCopy.dsAnchors.clear();
976 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
977 g_luaconfs.setState(luaconfsCopy);
978
979 auto dckeRRSIG = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
980 dckeRRSIG->create(dckeRRSIG->getBits());
981 DNSSECPrivateKey rrsigkey;
982 rrsigkey.d_flags = 257;
983 rrsigkey.setKey(std::move(dckeRRSIG));
984 DSRecordContent rrsigds = makeDSFromDNSKey(target, rrsigkey.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
985
986 rrsigkeys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(rrsigkey, rrsigds);
987
988 size_t queriesCount = 0;
989
990 sr->setAsyncCallback([target, &queriesCount, keys, rrsigkeys](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) {
991 queriesCount++;
992
993 if (domain == target && type == QType::NS) {
994
995 setLWResult(res, 0, true, false, true);
996 char addr[] = "a.root-servers.net.";
997 for (char idx = 'a'; idx <= 'm'; idx++) {
998 addr[0] = idx;
999 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
1000 }
1001
1002 addRRSIG(rrsigkeys, res->d_records, domain, 300);
1003
1004 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1005 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1006
1007 return LWResult::Result::Success;
1008 }
1009 else if (domain == target && type == QType::DNSKEY) {
1010
1011 setLWResult(res, 0, true, false, true);
1012
1013 addDNSKEY(keys, domain, 300, res->d_records);
1014 addRRSIG(rrsigkeys, res->d_records, domain, 300);
1015
1016 return LWResult::Result::Success;
1017 }
1018
1019 return LWResult::Result::Timeout;
1020 });
1021
1022 vector<DNSRecord> ret;
1023 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1024 BOOST_CHECK_EQUAL(res, RCode::NoError);
1025 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
1026 /* 13 NS + 1 RRSIG */
1027 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1028 BOOST_CHECK_EQUAL(queriesCount, 2U);
1029
1030 /* again, to test the cache */
1031 ret.clear();
1032 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1033 BOOST_CHECK_EQUAL(res, RCode::NoError);
1034 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
1035 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1036 BOOST_CHECK_EQUAL(queriesCount, 2U);
1037 }
1038
1039 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig)
1040 {
1041 std::unique_ptr<SyncRes> sr;
1042 initSR(sr, true);
1043
1044 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1045
1046 primeHints();
1047 const DNSName target(".");
1048 testkeysset_t keys;
1049
1050 auto luaconfsCopy = g_luaconfs.getCopy();
1051 luaconfsCopy.dsAnchors.clear();
1052 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1053 g_luaconfs.setState(luaconfsCopy);
1054
1055 size_t queriesCount = 0;
1056
1057 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) {
1058 queriesCount++;
1059
1060 if (domain == target && type == QType::NS) {
1061
1062 setLWResult(res, 0, true, false, true);
1063 char addr[] = "a.root-servers.net.";
1064 for (char idx = 'a'; idx <= 'm'; idx++) {
1065 addr[0] = idx;
1066 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 86400);
1067 }
1068
1069 /* No RRSIG */
1070
1071 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1072 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1073
1074 return LWResult::Result::Success;
1075 }
1076 else if (domain == target && type == QType::DNSKEY) {
1077
1078 setLWResult(res, 0, true, false, true);
1079
1080 addDNSKEY(keys, domain, 300, res->d_records);
1081 addRRSIG(keys, res->d_records, domain, 300);
1082
1083 return LWResult::Result::Success;
1084 }
1085
1086 return LWResult::Result::Timeout;
1087 });
1088
1089 SyncRes::s_maxcachettl = 86400;
1090 SyncRes::s_maxbogusttl = 3600;
1091
1092 vector<DNSRecord> ret;
1093 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1094 BOOST_CHECK_EQUAL(res, RCode::NoError);
1095 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1096 /* 13 NS + 0 RRSIG */
1097 BOOST_REQUIRE_EQUAL(ret.size(), 13U);
1098 /* no RRSIG so no query for DNSKEYs */
1099 BOOST_CHECK_EQUAL(queriesCount, 1U);
1100
1101 /* again, to test the cache */
1102 ret.clear();
1103 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1104 BOOST_CHECK_EQUAL(res, RCode::NoError);
1105 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1106 BOOST_REQUIRE_EQUAL(ret.size(), 13U);
1107 /* check that we capped the TTL to max-cache-bogus-ttl */
1108 for (const auto& record : ret) {
1109 BOOST_CHECK_LE(record.d_ttl, SyncRes::s_maxbogusttl);
1110 }
1111 BOOST_CHECK_EQUAL(queriesCount, 1U);
1112 }
1113
1114 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig_noaa)
1115 {
1116 std::unique_ptr<SyncRes> sr;
1117 initSR(sr, true);
1118
1119 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1120
1121 primeHints();
1122 const DNSName target(".");
1123 testkeysset_t keys;
1124
1125 auto luaconfsCopy = g_luaconfs.getCopy();
1126 luaconfsCopy.dsAnchors.clear();
1127 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1128 g_luaconfs.setState(luaconfsCopy);
1129
1130 size_t queriesCount = 0;
1131
1132 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) {
1133 queriesCount++;
1134
1135 if (domain == target && type == QType::NS) {
1136
1137 /* We are not setting AA! */
1138 setLWResult(res, 0, false, false, true);
1139 char addr[] = "a.root-servers.net.";
1140 for (char idx = 'a'; idx <= 'm'; idx++) {
1141 addr[0] = idx;
1142 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 86400);
1143 }
1144
1145 /* No RRSIG */
1146
1147 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1148 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1149
1150 return LWResult::Result::Success;
1151 }
1152 else if (domain == target && type == QType::DNSKEY) {
1153
1154 setLWResult(res, 0, true, false, true);
1155
1156 addDNSKEY(keys, domain, 300, res->d_records);
1157 addRRSIG(keys, res->d_records, domain, 300);
1158
1159 return LWResult::Result::Success;
1160 }
1161
1162 return LWResult::Result::Timeout;
1163 });
1164
1165 SyncRes::s_maxcachettl = 86400;
1166 SyncRes::s_maxbogusttl = 3600;
1167
1168 vector<DNSRecord> ret;
1169 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1170 BOOST_CHECK_EQUAL(res, RCode::NoError);
1171 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1172 /* 13 NS + 0 RRSIG */
1173 BOOST_REQUIRE_EQUAL(ret.size(), 13U);
1174 /* no RRSIG so no query for DNSKEYs */
1175 BOOST_CHECK_EQUAL(queriesCount, 1U);
1176
1177 /* again, to test the cache */
1178 ret.clear();
1179 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1180 BOOST_CHECK_EQUAL(res, RCode::NoError);
1181 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1182 BOOST_REQUIRE_EQUAL(ret.size(), 13U);
1183 /* check that we capped the TTL to max-cache-bogus-ttl */
1184 for (const auto& record : ret) {
1185 BOOST_CHECK_LE(record.d_ttl, SyncRes::s_maxbogusttl);
1186 }
1187 BOOST_CHECK_EQUAL(queriesCount, 1U);
1188 }
1189
1190 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm)
1191 {
1192 std::unique_ptr<SyncRes> sr;
1193 initSR(sr, true);
1194
1195 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1196
1197 primeHints();
1198 const DNSName target(".");
1199 testkeysset_t keys;
1200
1201 /* Generate key material for "." */
1202 auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
1203 dcke->create(dcke->getBits());
1204 DNSSECPrivateKey dpk;
1205 dpk.d_flags = 256;
1206 dpk.setKey(std::move(dcke));
1207 /* Fake algorithm number (private) */
1208 dpk.d_algorithm = 253;
1209
1210 DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
1211 keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc);
1212 /* Fake algorithm number (private) */
1213 drc.d_algorithm = 253;
1214
1215 /* Set the root DS */
1216 auto luaconfsCopy = g_luaconfs.getCopy();
1217 luaconfsCopy.dsAnchors.clear();
1218 luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
1219 g_luaconfs.setState(luaconfsCopy);
1220
1221 size_t queriesCount = 0;
1222
1223 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) {
1224 queriesCount++;
1225
1226 if (domain == target && type == QType::NS) {
1227
1228 setLWResult(res, 0, true, false, true);
1229 char addr[] = "a.root-servers.net.";
1230 for (char idx = 'a'; idx <= 'm'; idx++) {
1231 addr[0] = idx;
1232 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
1233 }
1234
1235 addRRSIG(keys, res->d_records, domain, 300);
1236
1237 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1238 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1239
1240 return LWResult::Result::Success;
1241 }
1242 else if (domain == target && type == QType::DNSKEY) {
1243
1244 setLWResult(res, 0, true, false, true);
1245
1246 addDNSKEY(keys, domain, 300, res->d_records);
1247 addRRSIG(keys, res->d_records, domain, 300);
1248
1249 return LWResult::Result::Success;
1250 }
1251
1252 return LWResult::Result::Timeout;
1253 });
1254
1255 vector<DNSRecord> ret;
1256 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1257 BOOST_CHECK_EQUAL(res, RCode::NoError);
1258 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1259 /* 13 NS + 1 RRSIG */
1260 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1261 /* no supported DS so no query for DNSKEYs */
1262 BOOST_CHECK_EQUAL(queriesCount, 1U);
1263
1264 /* again, to test the cache */
1265 ret.clear();
1266 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1267 BOOST_CHECK_EQUAL(res, RCode::NoError);
1268 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1269 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1270 BOOST_CHECK_EQUAL(queriesCount, 1U);
1271 }
1272
1273 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest)
1274 {
1275 std::unique_ptr<SyncRes> sr;
1276 initSR(sr, true);
1277
1278 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1279
1280 primeHints();
1281 const DNSName target(".");
1282 testkeysset_t keys;
1283
1284 /* Generate key material for "." */
1285 auto dcke = DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256);
1286 dcke->create(dcke->getBits());
1287 DNSSECPrivateKey dpk;
1288 dpk.d_flags = 256;
1289 dpk.setKey(std::move(dcke));
1290 DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::DIGEST_SHA256);
1291 /* Fake digest number (reserved) */
1292 drc.d_digesttype = 0;
1293
1294 keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc);
1295
1296 /* Set the root DS */
1297 auto luaconfsCopy = g_luaconfs.getCopy();
1298 luaconfsCopy.dsAnchors.clear();
1299 luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
1300 g_luaconfs.setState(luaconfsCopy);
1301
1302 size_t queriesCount = 0;
1303
1304 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) {
1305 queriesCount++;
1306
1307 if (domain == target && type == QType::NS) {
1308
1309 setLWResult(res, 0, true, false, true);
1310 char addr[] = "a.root-servers.net.";
1311 for (char idx = 'a'; idx <= 'm'; idx++) {
1312 addr[0] = idx;
1313 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
1314 }
1315
1316 addRRSIG(keys, res->d_records, domain, 300);
1317
1318 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1319 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1320
1321 return LWResult::Result::Success;
1322 }
1323 else if (domain == target && type == QType::DNSKEY) {
1324
1325 setLWResult(res, 0, true, false, true);
1326
1327 addDNSKEY(keys, domain, 300, res->d_records);
1328 addRRSIG(keys, res->d_records, domain, 300);
1329
1330 return LWResult::Result::Success;
1331 }
1332
1333 return LWResult::Result::Timeout;
1334 });
1335
1336 vector<DNSRecord> ret;
1337 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1338 BOOST_CHECK_EQUAL(res, RCode::NoError);
1339 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1340 /* 13 NS + 1 RRSIG */
1341 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1342 /* no supported DS so no query for DNSKEYs */
1343 BOOST_CHECK_EQUAL(queriesCount, 1U);
1344
1345 /* again, to test the cache */
1346 ret.clear();
1347 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1348 BOOST_CHECK_EQUAL(res, RCode::NoError);
1349 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
1350 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1351 BOOST_CHECK_EQUAL(queriesCount, 1U);
1352 }
1353
1354 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig)
1355 {
1356 std::unique_ptr<SyncRes> sr;
1357 initSR(sr, true);
1358
1359 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1360
1361 primeHints();
1362 const DNSName target(".");
1363 testkeysset_t keys;
1364
1365 auto luaconfsCopy = g_luaconfs.getCopy();
1366 luaconfsCopy.dsAnchors.clear();
1367 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
1368
1369 g_luaconfs.setState(luaconfsCopy);
1370 /* make sure that the signature inception and validity times are computed
1371 based on the SyncRes time, not the current one, in case the function
1372 takes too long. */
1373 const time_t fixedNow = sr->getNow().tv_sec;
1374
1375 size_t queriesCount = 0;
1376
1377 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) {
1378 queriesCount++;
1379
1380 if (domain == target && type == QType::NS) {
1381
1382 setLWResult(res, 0, true, false, true);
1383 char addr[] = "a.root-servers.net.";
1384 for (char idx = 'a'; idx <= 'm'; idx++) {
1385 addr[0] = idx;
1386 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
1387 }
1388
1389 addRRSIG(keys, res->d_records, domain, 300, true, boost::none, boost::none, fixedNow);
1390
1391 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1392 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1393
1394 return LWResult::Result::Success;
1395 }
1396 else if (domain == target && type == QType::DNSKEY) {
1397
1398 setLWResult(res, 0, true, false, true);
1399
1400 addDNSKEY(keys, domain, 300, res->d_records);
1401 addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, fixedNow);
1402
1403 return LWResult::Result::Success;
1404 }
1405
1406 return LWResult::Result::Timeout;
1407 });
1408
1409 vector<DNSRecord> ret;
1410 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1411 BOOST_CHECK_EQUAL(res, RCode::NoError);
1412 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
1413 /* 13 NS + 1 RRSIG */
1414 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1415 BOOST_CHECK_EQUAL(queriesCount, 2U);
1416
1417 /* again, to test the cache */
1418 ret.clear();
1419 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1420 BOOST_CHECK_EQUAL(res, RCode::NoError);
1421 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
1422 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1423 BOOST_CHECK_EQUAL(queriesCount, 2U);
1424 }
1425
1426 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo)
1427 {
1428 std::unique_ptr<SyncRes> sr;
1429 initSR(sr, true);
1430
1431 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1432
1433 primeHints();
1434 const DNSName target(".");
1435 testkeysset_t keys;
1436
1437 auto luaconfsCopy = g_luaconfs.getCopy();
1438 luaconfsCopy.dsAnchors.clear();
1439 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
1440
1441 g_luaconfs.setState(luaconfsCopy);
1442
1443 size_t queriesCount = 0;
1444
1445 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) {
1446 queriesCount++;
1447
1448 if (domain == target && type == QType::NS) {
1449
1450 setLWResult(res, 0, true, false, true);
1451 char addr[] = "a.root-servers.net.";
1452 for (char idx = 'a'; idx <= 'm'; idx++) {
1453 addr[0] = idx;
1454 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
1455 }
1456
1457 /* FORCE WRONG ALGO */
1458 addRRSIG(keys, res->d_records, domain, 300, false, DNSSECKeeper::RSASHA256);
1459
1460 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
1461 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
1462
1463 return LWResult::Result::Success;
1464 }
1465 else if (domain == target && type == QType::DNSKEY) {
1466
1467 setLWResult(res, 0, true, false, true);
1468
1469 addDNSKEY(keys, domain, 300, res->d_records);
1470 addRRSIG(keys, res->d_records, domain, 300);
1471
1472 return LWResult::Result::Success;
1473 }
1474
1475 return LWResult::Result::Timeout;
1476 });
1477
1478 vector<DNSRecord> ret;
1479 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1480 BOOST_CHECK_EQUAL(res, RCode::NoError);
1481 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
1482 /* 13 NS + 1 RRSIG */
1483 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1484 BOOST_CHECK_EQUAL(queriesCount, 2U);
1485
1486 /* again, to test the cache */
1487 ret.clear();
1488 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
1489 BOOST_CHECK_EQUAL(res, RCode::NoError);
1490 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoValidRRSIG);
1491 BOOST_REQUIRE_EQUAL(ret.size(), 14U);
1492 BOOST_CHECK_EQUAL(queriesCount, 2U);
1493 }
1494
1495 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds)
1496 {
1497 std::unique_ptr<SyncRes> sr;
1498 initSR(sr, true);
1499
1500 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1501
1502 primeHints();
1503 const DNSName target("com.");
1504 const ComboAddress targetAddr("192.0.2.42");
1505 testkeysset_t keys;
1506
1507 auto luaconfsCopy = g_luaconfs.getCopy();
1508 luaconfsCopy.dsAnchors.clear();
1509 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
1510 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1511
1512 g_luaconfs.setState(luaconfsCopy);
1513
1514 size_t queriesCount = 0;
1515
1516 sr->setAsyncCallback([target, targetAddr, &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) {
1517 queriesCount++;
1518
1519 DNSName auth = domain;
1520
1521 if (type == QType::DS || type == QType::DNSKEY) {
1522 if (genericDSAndDNSKEYHandler(res, domain, auth, type, keys) == LWResult::Result::Timeout) {
1523 return LWResult::Result::Timeout;
1524 }
1525
1526 if (type == QType::DS && domain == target) {
1527 /* remove the last record, which is the DS's RRSIG */
1528 res->d_records.pop_back();
1529 }
1530
1531 return LWResult::Result::Success;
1532 }
1533
1534 if (isRootServer(ip)) {
1535 setLWResult(res, 0, false, false, true);
1536 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
1537 /* Include the DS but omit the RRSIG*/
1538 addDS(DNSName("com."), 300, res->d_records, keys);
1539 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1540 return LWResult::Result::Success;
1541 }
1542
1543 if (ip == ComboAddress("192.0.2.1:53")) {
1544 setLWResult(res, RCode::NoError, true, false, true);
1545 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
1546 addRRSIG(keys, res->d_records, auth, 300);
1547 return LWResult::Result::Success;
1548 }
1549
1550 return LWResult::Result::Timeout;
1551 });
1552
1553 vector<DNSRecord> ret;
1554 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1555 BOOST_CHECK_EQUAL(res, RCode::NoError);
1556 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1557 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1558 BOOST_CHECK_EQUAL(queriesCount, 3U);
1559
1560 /* again, to test the cache */
1561 ret.clear();
1562 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1563 BOOST_CHECK_EQUAL(res, RCode::NoError);
1564 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1565 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1566 BOOST_CHECK_EQUAL(queriesCount, 3U);
1567
1568 /* now we ask directly for the DS */
1569 ret.clear();
1570 res = sr->beginResolve(DNSName("com."), QType(QType::DS), QClass::IN, ret);
1571 BOOST_CHECK_EQUAL(res, RCode::NoError);
1572 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1573 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1574 BOOST_CHECK_EQUAL(queriesCount, 3U);
1575 }
1576
1577 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds_direct)
1578 {
1579 std::unique_ptr<SyncRes> sr;
1580 initSR(sr, true);
1581
1582 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1583
1584 primeHints();
1585 const DNSName target("com.");
1586 testkeysset_t keys;
1587
1588 auto luaconfsCopy = g_luaconfs.getCopy();
1589 luaconfsCopy.dsAnchors.clear();
1590 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::DIGEST_SHA384, keys, luaconfsCopy.dsAnchors);
1591 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1592
1593 g_luaconfs.setState(luaconfsCopy);
1594
1595 size_t queriesCount = 0;
1596
1597 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) {
1598 queriesCount++;
1599
1600 DNSName auth = domain;
1601
1602 if (type == QType::DS || type == QType::DNSKEY) {
1603 if (genericDSAndDNSKEYHandler(res, domain, auth, type, keys) == LWResult::Result::Timeout) {
1604 return LWResult::Result::Timeout;
1605 }
1606
1607 if (type == QType::DS && domain == target) {
1608 /* remove the last record, which is the DS's RRSIG */
1609 res->d_records.pop_back();
1610 }
1611
1612 return LWResult::Result::Success;
1613 }
1614
1615 if (isRootServer(ip)) {
1616 setLWResult(res, 0, false, false, true);
1617 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
1618 /* Include the DS but omit the RRSIG*/
1619 addDS(DNSName("com."), 300, res->d_records, keys);
1620 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1621 return LWResult::Result::Success;
1622 }
1623
1624 return LWResult::Result::Timeout;
1625 });
1626
1627 vector<DNSRecord> ret;
1628 int res = sr->beginResolve(DNSName("com."), QType(QType::DS), QClass::IN, ret);
1629 BOOST_CHECK_EQUAL(res, RCode::NoError);
1630 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1631 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1632 BOOST_CHECK_EQUAL(queriesCount, 1U);
1633 }
1634
1635 BOOST_AUTO_TEST_SUITE_END()