]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursordist/test-syncres_cc4.cc
rec: CVE-2023-50387 and CVE-2023-50868
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc4.cc
CommitLineData
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
9BOOST_AUTO_TEST_SUITE(syncres_cc4)
10
42dcf516
OM
11BOOST_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
57BOOST_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
96BOOST_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
174BOOST_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
236BOOST_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
283BOOST_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
341BOOST_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
388BOOST_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
439BOOST_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
469BOOST_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
536BOOST_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
622BOOST_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
688BOOST_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
764BOOST_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
840BOOST_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
960BOOST_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
1036BOOST_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
1052Algorithm: 13 (ECDSAP256SHA256)
1053PrivateKey: 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
1062Algorithm: 13 (ECDSAP256SHA256)
1063PrivateKey: 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
1135BOOST_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
1152Algorithm: 13 (ECDSAP256SHA256)
1153PrivateKey: 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
1162Algorithm: 13 (ECDSAP256SHA256)
1163PrivateKey: 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
1237BOOST_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
1313BOOST_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
1388BOOST_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
1464BOOST_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
1545BOOST_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
1625BOOST_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
1697BOOST_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
1775BOOST_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
1839BOOST_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
1908BOOST_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
1990BOOST_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
2048BOOST_AUTO_TEST_SUITE_END()