1 #ifndef BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_DYN_LINK
5 #include <boost/test/unit_test.hpp>
7 #include "test-syncres_cc.hh"
9 BOOST_AUTO_TEST_SUITE(syncres_cc5
)
11 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos
)
13 std::unique_ptr
<SyncRes
> sr
;
16 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
19 const DNSName
target("powerdns.com.");
20 const ComboAddress
targetAddr("192.0.2.42");
23 auto luaconfsCopy
= g_luaconfs
.getCopy();
24 luaconfsCopy
.dsAnchors
.clear();
25 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::DIGEST_SHA384
, keys
, luaconfsCopy
.dsAnchors
);
26 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
27 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384
, DNSSECKeeper::DIGEST_SHA384
, keys
);
29 g_luaconfs
.setState(luaconfsCopy
);
31 size_t queriesCount
= 0;
33 /* make sure that the signature inception and validity times are computed
34 based on the SyncRes time, not the current one, in case the function
37 const time_t fixedNow
= sr
->getNow().tv_sec
;
39 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 */) {
42 DNSName auth
= domain
;
43 if (domain
== target
) {
44 auth
= DNSName("powerdns.com.");
47 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
48 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, true, fixedNow
);
51 if (isRootServer(address
)) {
52 setLWResult(res
, 0, false, false, true);
53 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
54 addDS(DNSName("com."), 300, res
->d_records
, keys
);
55 addRRSIG(keys
, res
->d_records
, DNSName("."), 300, false, boost::none
, boost::none
, fixedNow
);
56 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
57 return LWResult::Result::Success
;
60 if (address
== ComboAddress("192.0.2.1:53")) {
61 if (domain
== DNSName("com.")) {
62 setLWResult(res
, 0, true, false, true);
63 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
64 addRRSIG(keys
, res
->d_records
, domain
, 300, false, boost::none
, boost::none
, fixedNow
);
65 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
66 addRRSIG(keys
, res
->d_records
, domain
, 300);
69 setLWResult(res
, 0, false, false, true);
70 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
71 addDS(auth
, 300, res
->d_records
, keys
);
72 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300, false, boost::none
, boost::none
, fixedNow
);
73 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
75 return LWResult::Result::Success
;
78 if (address
== ComboAddress("192.0.2.2:53")) {
79 if (type
== QType::NS
) {
80 setLWResult(res
, 0, true, false, true);
81 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
82 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
83 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
84 addRRSIG(keys
, res
->d_records
, auth
, 300);
87 setLWResult(res
, RCode::NoError
, true, false, true);
88 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
89 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
91 return LWResult::Result::Success
;
94 return LWResult::Result::Timeout
;
97 vector
<DNSRecord
> ret
;
98 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
99 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
100 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
101 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
102 BOOST_CHECK_EQUAL(queriesCount
, 6U);
104 /* again, to test the cache */
106 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
107 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
108 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
109 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
110 BOOST_CHECK_EQUAL(queriesCount
, 6U);
113 static void testFixedPointInTime(time_t fixedNow
)
115 std::unique_ptr
<SyncRes
> sr
;
116 initSR(sr
, true, false, fixedNow
);
118 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
120 primeHints(fixedNow
);
121 const DNSName
target("powerdns.com.");
122 const ComboAddress
targetAddr("192.0.2.42");
125 auto luaconfsCopy
= g_luaconfs
.getCopy();
126 luaconfsCopy
.dsAnchors
.clear();
127 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::DIGEST_SHA384
, keys
, luaconfsCopy
.dsAnchors
);
128 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
129 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384
, DNSSECKeeper::DIGEST_SHA384
, keys
);
131 g_luaconfs
.setState(luaconfsCopy
);
133 size_t queriesCount
= 0;
135 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 */) {
138 DNSName auth
= domain
;
139 if (domain
== target
) {
140 auth
= DNSName("powerdns.com.");
143 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
144 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, true, fixedNow
);
147 if (isRootServer(address
)) {
148 setLWResult(res
, 0, false, false, true);
149 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
150 addDS(DNSName("com."), 300, res
->d_records
, keys
);
151 addRRSIG(keys
, res
->d_records
, DNSName("."), 300, false, boost::none
, boost::none
, fixedNow
);
152 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
153 return LWResult::Result::Success
;
156 if (address
== ComboAddress("192.0.2.1:53")) {
157 if (domain
== DNSName("com.")) {
158 setLWResult(res
, 0, true, false, true);
159 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
160 addRRSIG(keys
, res
->d_records
, domain
, 300, false, boost::none
, boost::none
, fixedNow
);
161 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
162 addRRSIG(keys
, res
->d_records
, domain
, 300, false, boost::none
, boost::none
, fixedNow
);
165 setLWResult(res
, 0, false, false, true);
166 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
167 addDS(auth
, 300, res
->d_records
, keys
);
168 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300, false, boost::none
, boost::none
, fixedNow
);
169 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
171 return LWResult::Result::Success
;
174 if (address
== ComboAddress("192.0.2.2:53")) {
175 if (type
== QType::NS
) {
176 setLWResult(res
, 0, true, false, true);
177 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
178 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
179 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
180 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
183 setLWResult(res
, RCode::NoError
, true, false, true);
184 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
185 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
187 return LWResult::Result::Success
;
190 return LWResult::Result::Timeout
;
193 vector
<DNSRecord
> ret
;
194 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
195 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
196 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
197 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
198 BOOST_CHECK_EQUAL(queriesCount
, 6U);
199 /* again, to test the cache */
201 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
202 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
203 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
204 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
205 BOOST_CHECK_EQUAL(queriesCount
, 6U);
208 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos1970
)
210 /* validity period in ye olde times */
211 const time_t fixedNow
= 1800;
212 testFixedPointInTime(fixedNow
);
215 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos2038
)
217 /* validity period contains the wrapping point in 2038 */
218 const time_t fixedNow
= INT_MAX
- 1800;
219 testFixedPointInTime(fixedNow
);
222 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos2041
)
224 /* validity period completely after 2038 but not wrapping uint32_t*/
225 const time_t fixedNow
= time_t(INT_MAX
) + 100000000;
226 testFixedPointInTime(fixedNow
);
230 // Currently fails see validate.cc:isRRSIGNotExpired() and isRRSIGIncepted()
231 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos2106
)
233 /* validity period beyond 2106 uint32_t wrapping point */
234 const time_t fixedNow
= 2 * time_t(INT_MAX
);
235 testFixedPointInTime(fixedNow
);
239 BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns
)
241 std::unique_ptr
<SyncRes
> sr
;
244 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
247 const DNSName
target("powerdns.com.");
248 const ComboAddress
targetAddr("192.0.2.42");
251 auto luaconfsCopy
= g_luaconfs
.getCopy();
252 luaconfsCopy
.dsAnchors
.clear();
253 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
254 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
255 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
256 g_luaconfs
.setState(luaconfsCopy
);
258 size_t queriesCount
= 0;
260 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 */) {
263 DNSName auth
= domain
;
264 if (domain
== target
) {
265 auth
= DNSName("powerdns.com.");
268 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
269 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
272 if (isRootServer(address
)) {
273 setLWResult(res
, 0, false, false, true);
274 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
275 addDS(DNSName("com."), 300, res
->d_records
, keys
);
276 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
277 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
278 return LWResult::Result::Success
;
281 if (address
== ComboAddress("192.0.2.1:53")) {
282 if (domain
== DNSName("com.")) {
283 setLWResult(res
, 0, true, false, true);
284 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
285 addRRSIG(keys
, res
->d_records
, domain
, 300);
286 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
287 addRRSIG(keys
, res
->d_records
, domain
, 300);
290 setLWResult(res
, 0, false, false, true);
291 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
292 addDS(auth
, 300, res
->d_records
, keys
);
293 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
294 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
296 return LWResult::Result::Success
;
299 if (address
== ComboAddress("192.0.2.2:53")) {
300 if (type
== QType::NS
) {
301 setLWResult(res
, 0, true, false, true);
302 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
303 addRRSIG(keys
, res
->d_records
, auth
, 300);
304 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
305 addRRSIG(keys
, res
->d_records
, auth
, 300);
308 setLWResult(res
, RCode::NoError
, true, false, true);
309 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
310 addRRSIG(keys
, res
->d_records
, auth
, 300);
312 return LWResult::Result::Success
;
315 return LWResult::Result::Timeout
;
318 vector
<DNSRecord
> ret
;
319 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
320 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
321 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
322 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
323 BOOST_CHECK_EQUAL(queriesCount
, 6U);
325 /* again, to test the cache */
327 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
328 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
329 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
330 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
331 BOOST_CHECK_EQUAL(queriesCount
, 6U);
333 /* this time we ask for the NS that should be in the cache, to check
334 the validation status */
336 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
337 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
338 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
339 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
340 BOOST_CHECK_EQUAL(queriesCount
, 7U);
343 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns
)
345 std::unique_ptr
<SyncRes
> sr
;
348 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
351 const DNSName
target("powerdns.com.");
352 const ComboAddress
targetAddr("192.0.2.42");
355 auto luaconfsCopy
= g_luaconfs
.getCopy();
356 luaconfsCopy
.dsAnchors
.clear();
357 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
358 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
359 g_luaconfs
.setState(luaconfsCopy
);
361 size_t queriesCount
= 0;
363 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 */) {
366 DNSName auth
= domain
;
367 if (domain
== target
) {
368 auth
= DNSName("powerdns.com.");
371 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
372 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
375 if (isRootServer(address
)) {
376 setLWResult(res
, 0, false, false, true);
377 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
378 addDS(DNSName("com."), 300, res
->d_records
, keys
);
379 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
380 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
381 return LWResult::Result::Success
;
384 if (address
== ComboAddress("192.0.2.1:53")) {
385 if (domain
== DNSName("com.")) {
386 setLWResult(res
, 0, true, false, true);
387 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
388 addRRSIG(keys
, res
->d_records
, domain
, 300);
389 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
390 addRRSIG(keys
, res
->d_records
, domain
, 300);
393 setLWResult(res
, 0, false, false, true);
394 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
396 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), {QType::NS
}, 600, res
->d_records
);
397 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
398 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
400 return LWResult::Result::Success
;
403 if (address
== ComboAddress("192.0.2.2:53")) {
404 if (type
== QType::NS
) {
405 setLWResult(res
, 0, true, false, true);
406 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
407 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
410 setLWResult(res
, RCode::NoError
, true, false, true);
411 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
413 return LWResult::Result::Success
;
416 return LWResult::Result::Timeout
;
419 vector
<DNSRecord
> ret
;
420 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
421 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
422 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
423 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
424 BOOST_CHECK_EQUAL(queriesCount
, 5U);
426 /* again, to test the cache */
428 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
429 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
430 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
431 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
432 BOOST_CHECK_EQUAL(queriesCount
, 5U);
434 /* this time we ask for the NS that should be in the cache, to check
435 the validation status */
437 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
438 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
439 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
440 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
441 BOOST_CHECK_EQUAL(queriesCount
, 6U);
444 BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta
)
446 std::unique_ptr
<SyncRes
> sr
;
449 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
452 const DNSName
target("powerdns.com.");
453 const ComboAddress
targetAddr("192.0.2.42");
456 auto luaconfsCopy
= g_luaconfs
.getCopy();
457 luaconfsCopy
.dsAnchors
.clear();
458 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
459 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
460 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
462 /* Add a NTA for "powerdns.com" */
463 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
465 g_luaconfs
.setState(luaconfsCopy
);
467 size_t queriesCount
= 0;
469 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 */) {
472 DNSName auth
= domain
;
473 if (domain
== target
) {
474 auth
= DNSName("powerdns.com.");
477 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
478 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
481 if (isRootServer(address
)) {
482 setLWResult(res
, 0, false, false, true);
483 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
484 addDS(DNSName("com."), 300, res
->d_records
, keys
);
485 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
486 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
487 return LWResult::Result::Success
;
490 if (address
== ComboAddress("192.0.2.1:53")) {
491 if (domain
== DNSName("com.")) {
492 setLWResult(res
, 0, true, false, true);
493 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
494 addRRSIG(keys
, res
->d_records
, domain
, 300);
495 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
496 addRRSIG(keys
, res
->d_records
, domain
, 300);
499 setLWResult(res
, 0, false, false, true);
500 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
501 addDS(auth
, 300, res
->d_records
, keys
);
502 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
503 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
505 return LWResult::Result::Success
;
508 if (address
== ComboAddress("192.0.2.2:53")) {
509 if (type
== QType::NS
) {
510 setLWResult(res
, 0, true, false, true);
511 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
512 addRRSIG(keys
, res
->d_records
, auth
, 300);
513 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
514 addRRSIG(keys
, res
->d_records
, auth
, 300);
517 setLWResult(res
, RCode::NoError
, true, false, true);
518 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
519 addRRSIG(keys
, res
->d_records
, auth
, 300);
521 return LWResult::Result::Success
;
524 return LWResult::Result::Timeout
;
527 vector
<DNSRecord
> ret
;
528 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
529 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
530 /* Should be insecure because of the NTA */
531 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
532 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
533 BOOST_CHECK_EQUAL(queriesCount
, 5U);
535 /* again, to test the cache */
537 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
538 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
539 /* Should be insecure because of the NTA */
540 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
541 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
542 BOOST_CHECK_EQUAL(queriesCount
, 5U);
545 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta
)
547 std::unique_ptr
<SyncRes
> sr
;
550 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
553 const DNSName
target("powerdns.com.");
554 const ComboAddress
targetAddr("192.0.2.42");
557 auto luaconfsCopy
= g_luaconfs
.getCopy();
558 luaconfsCopy
.dsAnchors
.clear();
559 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
560 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
561 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
563 /* Add a NTA for "powerdns.com" */
564 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
566 g_luaconfs
.setState(luaconfsCopy
);
568 size_t queriesCount
= 0;
570 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 */) {
573 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
574 setLWResult(res
, 0, true, false, true);
575 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
576 return LWResult::Result::Success
;
579 if (isRootServer(address
)) {
580 setLWResult(res
, 0, false, false, true);
581 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
582 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
583 return LWResult::Result::Success
;
585 if (address
== ComboAddress("192.0.2.1:53")) {
586 if (domain
== DNSName("com.")) {
587 setLWResult(res
, 0, true, false, true);
588 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
589 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
592 setLWResult(res
, 0, false, false, true);
593 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
594 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
596 return LWResult::Result::Success
;
598 if (address
== ComboAddress("192.0.2.2:53")) {
599 if (type
== QType::NS
) {
600 setLWResult(res
, 0, true, false, true);
601 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
602 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
605 setLWResult(res
, RCode::NoError
, true, false, true);
606 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
608 return LWResult::Result::Success
;
612 return LWResult::Result::Timeout
;
615 /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
616 vector
<DNSRecord
> ret
;
617 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
618 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
619 /* Should be insecure because of the NTA */
620 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
621 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
622 BOOST_CHECK_EQUAL(queriesCount
, 3U);
624 /* again, to test the cache */
626 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
627 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
628 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
629 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
630 BOOST_CHECK_EQUAL(queriesCount
, 3U);
633 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec
)
635 std::unique_ptr
<SyncRes
> sr
;
638 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
641 const DNSName
target("powerdns.com.");
644 auto luaconfsCopy
= g_luaconfs
.getCopy();
645 luaconfsCopy
.dsAnchors
.clear();
646 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
647 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
648 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
650 g_luaconfs
.setState(luaconfsCopy
);
652 size_t queriesCount
= 0;
654 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 */) {
657 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
658 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
661 if (isRootServer(address
)) {
662 setLWResult(res
, 0, false, false, true);
663 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
664 addDS(DNSName("com."), 300, res
->d_records
, keys
);
665 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
666 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
667 return LWResult::Result::Success
;
669 if (address
== ComboAddress("192.0.2.1:53")) {
670 if (domain
== DNSName("com.")) {
671 setLWResult(res
, 0, true, false, true);
672 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
673 addRRSIG(keys
, res
->d_records
, domain
, 300);
674 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
675 addRRSIG(keys
, res
->d_records
, domain
, 300);
678 setLWResult(res
, 0, false, false, true);
679 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
680 addDS(domain
, 300, res
->d_records
, keys
);
681 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
682 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
684 return LWResult::Result::Success
;
686 if (address
== ComboAddress("192.0.2.2:53")) {
687 if (type
== QType::NS
) {
688 setLWResult(res
, 0, true, false, true);
689 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
690 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
691 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
692 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
695 setLWResult(res
, 0, true, false, true);
696 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
697 addRRSIG(keys
, res
->d_records
, domain
, 300);
698 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), {QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
699 addRRSIG(keys
, res
->d_records
, domain
, 300);
701 return LWResult::Result::Success
;
705 return LWResult::Result::Timeout
;
708 vector
<DNSRecord
> ret
;
709 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
710 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
711 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
712 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
713 BOOST_CHECK_EQUAL(queriesCount
, 6U);
715 /* again, to test the cache */
717 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
718 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
719 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
720 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
721 BOOST_CHECK_EQUAL(queriesCount
, 6U);
724 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec
)
726 std::unique_ptr
<SyncRes
> sr
;
729 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
732 const DNSName
target("nx.powerdns.com.");
735 auto luaconfsCopy
= g_luaconfs
.getCopy();
736 luaconfsCopy
.dsAnchors
.clear();
737 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
738 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
739 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
741 g_luaconfs
.setState(luaconfsCopy
);
743 size_t queriesCount
= 0;
745 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 */) {
748 DNSName auth
= domain
;
749 if (domain
== target
) {
750 auth
= DNSName("powerdns.com.");
752 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
753 if (type
== QType::DS
&& domain
== target
) {
754 setLWResult(res
, RCode::NXDomain
, true, false, true);
755 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
756 addRRSIG(keys
, res
->d_records
, auth
, 300);
757 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
758 addRRSIG(keys
, res
->d_records
, auth
, 300);
759 return LWResult::Result::Success
;
761 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
764 if (isRootServer(address
)) {
765 setLWResult(res
, 0, false, false, true);
766 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
767 addDS(DNSName("com."), 300, res
->d_records
, keys
);
768 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
769 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
770 return LWResult::Result::Success
;
772 if (address
== ComboAddress("192.0.2.1:53")) {
773 if (domain
== DNSName("com.")) {
774 setLWResult(res
, 0, true, false, true);
775 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
776 addRRSIG(keys
, res
->d_records
, domain
, 300);
777 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
778 addRRSIG(keys
, res
->d_records
, domain
, 300);
781 setLWResult(res
, 0, false, false, true);
782 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
783 addDS(auth
, 300, res
->d_records
, keys
);
784 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
785 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
787 return LWResult::Result::Success
;
789 if (address
== ComboAddress("192.0.2.2:53")) {
790 if (type
== QType::NS
) {
791 setLWResult(res
, 0, true, false, true);
792 if (domain
== DNSName("powerdns.com.")) {
793 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
794 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
795 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
796 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
799 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
800 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
801 addNSECRecordToLW(DNSName("nx.powerdns.com."), DNSName("nz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
802 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
806 setLWResult(res
, RCode::NXDomain
, true, false, true);
807 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
808 addRRSIG(keys
, res
->d_records
, auth
, 300);
809 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
810 addRRSIG(keys
, res
->d_records
, auth
, 300);
811 /* add wildcard denial */
812 addNSECRecordToLW(DNSName("powerdns.com."), DNSName("a.powerdns.com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
813 addRRSIG(keys
, res
->d_records
, auth
, 300);
815 return LWResult::Result::Success
;
819 return LWResult::Result::Timeout
;
822 vector
<DNSRecord
> ret
;
823 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
824 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
825 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
826 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
827 BOOST_CHECK_EQUAL(queriesCount
, 6U);
829 /* again, to test the cache */
831 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
832 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
833 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
834 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
835 BOOST_CHECK_EQUAL(queriesCount
, 6U);
838 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard
)
840 std::unique_ptr
<SyncRes
> sr
;
843 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
846 const DNSName
target("www.powerdns.com.");
849 auto luaconfsCopy
= g_luaconfs
.getCopy();
850 luaconfsCopy
.dsAnchors
.clear();
851 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
852 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
853 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
855 g_luaconfs
.setState(luaconfsCopy
);
857 size_t queriesCount
= 0;
859 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 */) {
862 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
863 if (type
== QType::DS
&& domain
== target
) {
864 setLWResult(res
, RCode::NoError
, true, false, true);
865 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
866 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
867 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
868 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
869 return LWResult::Result::Success
;
871 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
874 if (isRootServer(address
)) {
875 setLWResult(res
, 0, false, false, true);
876 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
877 addDS(DNSName("com."), 300, res
->d_records
, keys
);
878 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
879 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
880 return LWResult::Result::Success
;
882 if (address
== ComboAddress("192.0.2.1:53")) {
883 if (domain
== DNSName("com.")) {
884 setLWResult(res
, 0, true, false, true);
885 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
886 addRRSIG(keys
, res
->d_records
, domain
, 300);
887 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
888 addRRSIG(keys
, res
->d_records
, domain
, 300);
891 setLWResult(res
, 0, false, false, true);
892 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
893 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
894 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
895 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
897 return LWResult::Result::Success
;
899 if (address
== ComboAddress("192.0.2.2:53")) {
900 setLWResult(res
, 0, true, false, true);
901 if (type
== QType::NS
) {
902 if (domain
== DNSName("powerdns.com.")) {
903 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
904 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
905 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
906 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
909 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
910 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
911 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
912 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
916 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, 600);
917 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
918 /* we need to add the proof that this name does not exist, so the wildcard may apply */
919 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 60, res
->d_records
);
920 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
922 return LWResult::Result::Success
;
926 return LWResult::Result::Timeout
;
929 vector
<DNSRecord
> ret
;
930 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
931 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
932 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
933 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
934 BOOST_CHECK_EQUAL(queriesCount
, 6U);
936 /* again, to test the cache */
938 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
939 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
940 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
941 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
942 for (const auto& rec
: ret
) {
943 /* check that we applied the lowest TTL, here this is from the NSEC proving that the exact name did not exist */
944 BOOST_CHECK_LE(rec
.d_ttl
, 60U);
946 BOOST_CHECK_EQUAL(queriesCount
, 6U);
949 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_proof_before_rrsig
)
951 /* this tests makes sure that we correctly detect that we need to gather
952 wildcard proof (since the answer is expanded from a wildcard, we need
953 to prove that the target name does not exist) even though the RRSIG which
954 allows us to detect that the answer is an expanded wildcard (from the label
955 count field of the RRSIG) comes _after_ the NSEC
957 std::unique_ptr
<SyncRes
> sr
;
960 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
963 const DNSName
target("www.powerdns.com.");
966 auto luaconfsCopy
= g_luaconfs
.getCopy();
967 luaconfsCopy
.dsAnchors
.clear();
968 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
969 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
970 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
972 g_luaconfs
.setState(luaconfsCopy
);
974 size_t queriesCount
= 0;
976 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 */) {
979 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
980 if (type
== QType::DS
&& domain
== target
) {
981 setLWResult(res
, RCode::NoError
, true, false, true);
982 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
983 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
984 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
985 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
986 return LWResult::Result::Success
;
988 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
991 if (isRootServer(address
)) {
992 setLWResult(res
, 0, false, false, true);
993 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
994 addDS(DNSName("com."), 300, res
->d_records
, keys
);
995 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
996 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
997 return LWResult::Result::Success
;
999 if (address
== ComboAddress("192.0.2.1:53")) {
1000 if (domain
== DNSName("com.")) {
1001 setLWResult(res
, 0, true, false, true);
1002 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
1003 addRRSIG(keys
, res
->d_records
, domain
, 300);
1004 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1005 addRRSIG(keys
, res
->d_records
, domain
, 300);
1008 setLWResult(res
, 0, false, false, true);
1009 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
1010 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
1011 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1012 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1014 return LWResult::Result::Success
;
1016 if (address
== ComboAddress("192.0.2.2:53")) {
1017 setLWResult(res
, 0, true, false, true);
1018 if (type
== QType::NS
) {
1019 if (domain
== DNSName("powerdns.com.")) {
1020 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
1021 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1022 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1023 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1026 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1027 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1028 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1029 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1033 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, 600);
1034 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1035 /* we need to add the proof that this name does not exist, so the wildcard may apply */
1036 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 60, res
->d_records
);
1037 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1038 /* now this is the important part! We are swapping the first RRSIG and the NSEC, to make sure we still gather the NSEC proof that the
1039 exact name does not exist even though we have not seen the RRSIG whose label count is smaller than the target name yet */
1040 std::swap(res
->d_records
.at(1), res
->d_records
.at(3));
1042 return LWResult::Result::Success
;
1046 return LWResult::Result::Timeout
;
1049 vector
<DNSRecord
> ret
;
1050 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1051 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1052 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1053 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
1054 BOOST_CHECK_EQUAL(queriesCount
, 6U);
1056 /* again, to test the cache */
1058 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1059 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1060 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1061 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
1062 for (const auto& rec
: ret
) {
1063 /* check that we applied the lowest TTL, here this is from the NSEC proving that the exact name did not exist */
1064 BOOST_CHECK_LE(rec
.d_ttl
, 60U);
1066 BOOST_CHECK_EQUAL(queriesCount
, 6U);
1069 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_nodata_nowildcard
)
1071 std::unique_ptr
<SyncRes
> sr
;
1074 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1077 const DNSName
target("www.com.");
1080 auto luaconfsCopy
= g_luaconfs
.getCopy();
1081 luaconfsCopy
.dsAnchors
.clear();
1082 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1083 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1085 g_luaconfs
.setState(luaconfsCopy
);
1087 size_t queriesCount
= 0;
1089 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 */) {
1092 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1093 if (type
== QType::DS
&& domain
== target
) {
1094 DNSName
auth("com.");
1095 setLWResult(res
, 0, true, false, true);
1097 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1098 addRRSIG(keys
, res
->d_records
, auth
, 300);
1099 /* add a NSEC denying the DS AND the existence of a cut (no NS) */
1100 addNSECRecordToLW(domain
, DNSName("z") + domain
, {QType::NSEC
}, 600, res
->d_records
);
1101 addRRSIG(keys
, res
->d_records
, auth
, 300);
1102 return LWResult::Result::Success
;
1104 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1107 if (isRootServer(address
)) {
1108 setLWResult(res
, 0, false, false, true);
1109 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
1110 addDS(DNSName("com."), 300, res
->d_records
, keys
);
1111 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1112 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1113 return LWResult::Result::Success
;
1115 if (address
== ComboAddress("192.0.2.1:53")) {
1116 setLWResult(res
, 0, true, false, true);
1118 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1119 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1120 /* no record for this name */
1121 addNSECRecordToLW(DNSName("wwv.com."), DNSName("wwx.com."), {QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1122 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1123 /* a wildcard matches but has no record for this type */
1124 addNSECRecordToLW(DNSName("*.com."), DNSName("com."), {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1125 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
1126 return LWResult::Result::Success
;
1130 return LWResult::Result::Timeout
;
1133 vector
<DNSRecord
> ret
;
1134 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1135 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1136 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1137 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
1138 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1140 /* again, to test the cache */
1142 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1143 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1144 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1145 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
1146 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1149 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard
)
1151 std::unique_ptr
<SyncRes
> sr
;
1154 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1157 const DNSName
target("www.com.");
1160 auto luaconfsCopy
= g_luaconfs
.getCopy();
1161 luaconfsCopy
.dsAnchors
.clear();
1162 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1163 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1165 g_luaconfs
.setState(luaconfsCopy
);
1167 size_t queriesCount
= 0;
1169 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 */) {
1172 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1173 if (type
== QType::DS
&& domain
== target
) {
1174 DNSName
auth("com.");
1175 setLWResult(res
, 0, true, false, true);
1177 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1178 addRRSIG(keys
, res
->d_records
, auth
, 300);
1179 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
1180 /* first the closest encloser */
1181 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1182 addRRSIG(keys
, res
->d_records
, auth
, 300);
1183 /* then the next closer */
1184 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1185 addRRSIG(keys
, res
->d_records
, auth
, 300);
1186 /* a wildcard matches but has no record for this type */
1187 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1188 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
1189 return LWResult::Result::Success
;
1191 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1194 if (isRootServer(address
)) {
1195 setLWResult(res
, 0, false, false, true);
1196 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
1197 addDS(DNSName("com."), 300, res
->d_records
, keys
);
1198 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1199 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1200 return LWResult::Result::Success
;
1202 if (address
== ComboAddress("192.0.2.1:53")) {
1203 setLWResult(res
, 0, true, false, true);
1205 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1206 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1207 /* no record for this name */
1208 /* first the closest encloser */
1209 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1210 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1211 /* then the next closer */
1212 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1213 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1214 /* a wildcard matches but has no record for this type */
1215 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1216 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
1217 return LWResult::Result::Success
;
1221 return LWResult::Result::Timeout
;
1224 vector
<DNSRecord
> ret
;
1225 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1226 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1227 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1228 BOOST_REQUIRE_EQUAL(ret
.size(), 8U);
1229 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1231 /* again, to test the cache */
1233 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1234 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1235 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1236 BOOST_REQUIRE_EQUAL(ret
.size(), 8U);
1237 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1240 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_duplicated_nsec3
)
1242 std::unique_ptr
<SyncRes
> sr
;
1245 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1248 const DNSName
target("www.com.");
1251 auto luaconfsCopy
= g_luaconfs
.getCopy();
1252 luaconfsCopy
.dsAnchors
.clear();
1253 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1254 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1256 g_luaconfs
.setState(luaconfsCopy
);
1258 size_t queriesCount
= 0;
1260 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 */) {
1263 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1264 if (type
== QType::DS
&& domain
== target
) {
1265 DNSName
auth("com.");
1266 setLWResult(res
, 0, true, false, true);
1268 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1269 addRRSIG(keys
, res
->d_records
, auth
, 300);
1270 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
1271 /* first the closest encloser */
1272 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1273 addRRSIG(keys
, res
->d_records
, auth
, 300);
1274 /* then the next closer */
1275 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1276 addRRSIG(keys
, res
->d_records
, auth
, 300);
1277 /* a wildcard matches but has no record for this type */
1278 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1279 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
1280 return LWResult::Result::Success
;
1282 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1285 if (isRootServer(address
)) {
1286 setLWResult(res
, 0, false, false, true);
1287 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
1288 addDS(DNSName("com."), 300, res
->d_records
, keys
);
1289 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1290 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1291 return LWResult::Result::Success
;
1293 if (address
== ComboAddress("192.0.2.1:53")) {
1294 setLWResult(res
, 0, true, false, true);
1296 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1297 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1298 /* no record for this name */
1299 /* first the closest encloser */
1300 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1301 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1302 /* !! we duplicate the NSEC3 on purpose, to check deduplication. The RRSIG will have been computed for a RRSET containing only one NSEC3 and should not be valid. */
1303 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1304 /* then the next closer */
1305 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1306 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1307 /* a wildcard matches but has no record for this type */
1308 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1309 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
1310 return LWResult::Result::Success
;
1314 return LWResult::Result::Timeout
;
1317 vector
<DNSRecord
> ret
;
1318 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1319 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1320 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1321 /* because we pass along the duplicated NSEC3 */
1322 BOOST_REQUIRE_EQUAL(ret
.size(), 9U);
1323 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1325 /* again, to test the cache */
1327 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1328 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1329 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1330 /* because we pass along the duplicated NSEC3 */
1331 BOOST_REQUIRE_EQUAL(ret
.size(), 9U);
1332 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1335 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_too_many_iterations
)
1337 std::unique_ptr
<SyncRes
> sr
;
1340 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1343 const DNSName
target("www.com.");
1346 auto luaconfsCopy
= g_luaconfs
.getCopy();
1347 luaconfsCopy
.dsAnchors
.clear();
1348 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1349 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1351 g_luaconfs
.setState(luaconfsCopy
);
1353 size_t queriesCount
= 0;
1355 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 */) {
1358 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1359 if (type
== QType::DS
&& domain
== target
) {
1360 DNSName
auth("com.");
1361 setLWResult(res
, 0, true, false, true);
1363 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1364 addRRSIG(keys
, res
->d_records
, auth
, 300);
1365 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
1366 /* first the closest encloser */
1367 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
1368 addRRSIG(keys
, res
->d_records
, auth
, 300);
1369 /* then the next closer */
1370 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
1371 addRRSIG(keys
, res
->d_records
, auth
, 300);
1372 /* a wildcard matches but has no record for this type */
1373 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
1374 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
1375 return LWResult::Result::Success
;
1377 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1380 if (isRootServer(address
)) {
1381 setLWResult(res
, 0, false, false, true);
1382 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
1383 addDS(DNSName("com."), 300, res
->d_records
, keys
);
1384 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1385 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1386 return LWResult::Result::Success
;
1388 if (address
== ComboAddress("192.0.2.1:53")) {
1389 setLWResult(res
, 0, true, false, true);
1391 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1392 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1393 /* no record for this name */
1394 /* first the closest encloser */
1395 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
1396 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1397 /* then the next closer */
1398 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
1399 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1400 /* a wildcard matches but has no record for this type */
1401 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
1402 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
1403 return LWResult::Result::Success
;
1407 return LWResult::Result::Timeout
;
1410 /* we are generating NSEC3 with more iterations than we allow, so we should go Insecure */
1411 vector
<DNSRecord
> ret
;
1412 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1413 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1414 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
1415 BOOST_REQUIRE_EQUAL(ret
.size(), 8U);
1416 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1418 /* again, to test the cache */
1420 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1421 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1422 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
1423 BOOST_REQUIRE_EQUAL(ret
.size(), 8U);
1424 BOOST_CHECK_EQUAL(queriesCount
, 4U);
1427 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard
)
1429 std::unique_ptr
<SyncRes
> sr
;
1432 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1435 const DNSName
target("www.sub.powerdns.com.");
1438 auto luaconfsCopy
= g_luaconfs
.getCopy();
1439 luaconfsCopy
.dsAnchors
.clear();
1440 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1441 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1442 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1444 g_luaconfs
.setState(luaconfsCopy
);
1446 size_t queriesCount
= 0;
1448 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 */) {
1451 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1452 if (type
== QType::DS
&& domain
.isPartOf(DNSName("sub.powerdns.com"))) {
1453 setLWResult(res
, RCode::NoError
, true, false, true);
1454 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1455 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1456 if (domain
== DNSName("sub.powerdns.com")) {
1457 addNSECRecordToLW(DNSName("sub.powerdns.com."), DNSName("sud.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1459 else if (domain
== target
) {
1460 addNSECRecordToLW(DNSName("www.sub.powerdns.com."), DNSName("wwz.sub.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1462 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1463 return LWResult::Result::Success
;
1465 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1468 if (isRootServer(address
)) {
1469 setLWResult(res
, 0, false, false, true);
1470 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
1471 addDS(DNSName("com."), 300, res
->d_records
, keys
);
1472 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1473 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1474 return LWResult::Result::Success
;
1476 if (address
== ComboAddress("192.0.2.1:53")) {
1477 if (domain
== DNSName("com.")) {
1478 setLWResult(res
, 0, true, false, true);
1479 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
1480 addRRSIG(keys
, res
->d_records
, domain
, 300);
1481 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1482 addRRSIG(keys
, res
->d_records
, domain
, 300);
1485 setLWResult(res
, 0, false, false, true);
1486 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
1487 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
1488 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1489 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1491 return LWResult::Result::Success
;
1493 if (address
== ComboAddress("192.0.2.2:53")) {
1494 setLWResult(res
, 0, true, false, true);
1495 if (type
== QType::NS
) {
1496 if (domain
== DNSName("powerdns.com.")) {
1497 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
1498 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1499 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1500 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1503 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1504 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1505 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1506 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1510 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, 600);
1511 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1512 /* we need to add the proof that this name does not exist, so the wildcard may apply */
1513 /* first the closest encloser */
1514 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1515 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1516 /* then the next closer */
1517 addNSEC3NarrowRecordToLW(DNSName("sub.powerdns.com."), DNSName("powerdns.com."), {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 60, res
->d_records
);
1518 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1520 return LWResult::Result::Success
;
1524 return LWResult::Result::Timeout
;
1527 vector
<DNSRecord
> ret
;
1528 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1529 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1530 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1531 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
1532 BOOST_CHECK_EQUAL(queriesCount
, 6U);
1534 /* again, to test the cache */
1536 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1537 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1538 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1539 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
1540 for (const auto& rec
: ret
) {
1541 /* check that we applied the lowest TTL, here this is from the NSEC3 proving that the exact name did not exist (next closer) */
1542 BOOST_CHECK_LE(rec
.d_ttl
, 60U);
1544 BOOST_CHECK_EQUAL(queriesCount
, 6U);
1547 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard_too_many_iterations
)
1549 std::unique_ptr
<SyncRes
> sr
;
1552 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1555 const DNSName
target("www.powerdns.com.");
1558 auto luaconfsCopy
= g_luaconfs
.getCopy();
1559 luaconfsCopy
.dsAnchors
.clear();
1560 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1561 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1562 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1564 g_luaconfs
.setState(luaconfsCopy
);
1566 size_t queriesCount
= 0;
1568 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 */) {
1571 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1572 if (type
== QType::DS
&& domain
== target
) {
1573 setLWResult(res
, RCode::NoError
, true, false, true);
1574 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1575 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1576 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1577 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1578 return LWResult::Result::Success
;
1580 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1583 if (isRootServer(address
)) {
1584 setLWResult(res
, 0, false, false, true);
1585 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
1586 addDS(DNSName("com."), 300, res
->d_records
, keys
);
1587 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1588 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1589 return LWResult::Result::Success
;
1591 if (address
== ComboAddress("192.0.2.1:53")) {
1592 if (domain
== DNSName("com.")) {
1593 setLWResult(res
, 0, true, false, true);
1594 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
1595 addRRSIG(keys
, res
->d_records
, domain
, 300);
1596 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1597 addRRSIG(keys
, res
->d_records
, domain
, 300);
1600 setLWResult(res
, 0, false, false, true);
1601 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
1602 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
1603 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1604 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1606 return LWResult::Result::Success
;
1608 if (address
== ComboAddress("192.0.2.2:53")) {
1609 setLWResult(res
, 0, true, false, true);
1610 if (type
== QType::NS
) {
1611 if (domain
== DNSName("powerdns.com.")) {
1612 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
1613 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1614 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1615 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1618 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1619 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1620 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1621 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1625 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
1626 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1627 /* we need to add the proof that this name does not exist, so the wildcard may apply */
1628 /* first the closest encloser */
1629 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
1630 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1631 /* then the next closer */
1632 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), {QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
1633 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1635 return LWResult::Result::Success
;
1639 return LWResult::Result::Timeout
;
1642 /* the NSEC3 providing the denial of existence proof for the next closer has too many iterations,
1643 we should end up Insecure */
1644 vector
<DNSRecord
> ret
;
1645 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1646 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1647 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
1648 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
1649 BOOST_CHECK_EQUAL(queriesCount
, 6U);
1651 /* again, to test the cache */
1653 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1654 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1655 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
1656 BOOST_REQUIRE_EQUAL(ret
.size(), 6U);
1657 BOOST_CHECK_EQUAL(queriesCount
, 6U);
1660 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_missing
)
1662 std::unique_ptr
<SyncRes
> sr
;
1665 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1668 const DNSName
target("www.powerdns.com.");
1671 auto luaconfsCopy
= g_luaconfs
.getCopy();
1672 luaconfsCopy
.dsAnchors
.clear();
1673 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1674 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1675 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1677 g_luaconfs
.setState(luaconfsCopy
);
1679 size_t queriesCount
= 0;
1681 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 */) {
1684 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1685 if (type
== QType::DS
&& domain
== target
) {
1686 setLWResult(res
, RCode::NoError
, true, false, true);
1687 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1688 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1689 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1690 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1691 return LWResult::Result::Success
;
1693 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1696 if (isRootServer(address
)) {
1697 setLWResult(res
, 0, false, false, true);
1698 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
1699 addDS(DNSName("com."), 300, res
->d_records
, keys
);
1700 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1701 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1702 return LWResult::Result::Success
;
1704 if (address
== ComboAddress("192.0.2.1:53")) {
1705 if (domain
== DNSName("com.")) {
1706 setLWResult(res
, 0, true, false, true);
1707 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
1708 addRRSIG(keys
, res
->d_records
, domain
, 300);
1709 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1710 addRRSIG(keys
, res
->d_records
, domain
, 300);
1713 setLWResult(res
, 0, false, false, true);
1714 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
1715 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
1716 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
1717 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1719 return LWResult::Result::Success
;
1721 if (address
== ComboAddress("192.0.2.2:53")) {
1722 setLWResult(res
, 0, true, false, true);
1723 if (type
== QType::NS
) {
1724 if (domain
== DNSName("powerdns.com.")) {
1725 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
1726 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1727 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1728 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1731 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1732 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1733 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1734 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
1738 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
1739 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1741 return LWResult::Result::Success
;
1745 return LWResult::Result::Timeout
;
1748 vector
<DNSRecord
> ret
;
1749 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1750 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1751 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::BogusInvalidDenial
);
1752 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1753 BOOST_CHECK_EQUAL(queriesCount
, 7U);
1755 /* again, to test the cache */
1757 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1758 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1759 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::BogusInvalidDenial
);
1760 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1761 BOOST_CHECK_EQUAL(queriesCount
, 7U);
1764 BOOST_AUTO_TEST_CASE(test_dnssec_validation_wildcard_expanded_onto_itself
)
1766 std::unique_ptr
<SyncRes
> sr
;
1769 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1772 const DNSName
target("*.powerdns.com.");
1775 auto luaconfsCopy
= g_luaconfs
.getCopy();
1776 luaconfsCopy
.dsAnchors
.clear();
1777 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1778 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1779 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1781 g_luaconfs
.setState(luaconfsCopy
);
1783 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 */) {
1784 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1785 if (domain
== target
) {
1786 const auto auth
= DNSName("powerdns.com.");
1787 /* we don't want a cut there */
1788 setLWResult(res
, 0, true, false, true);
1789 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1790 addRRSIG(keys
, res
->d_records
, auth
, 300);
1791 /* add a NSEC denying the DS */
1792 std::set
<uint16_t> types
= {QType::NSEC
};
1793 addNSECRecordToLW(domain
, DNSName("z") + domain
, types
, 600, res
->d_records
);
1794 addRRSIG(keys
, res
->d_records
, auth
, 300);
1795 return LWResult::Result::Success
;
1797 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1800 setLWResult(res
, 0, true, false, true);
1801 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
1802 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300, false, boost::none
, DNSName("*.powerdns.com"));
1803 /* we don't _really_ need to add the proof that the exact name does not exist because it does,
1804 it's the wildcard itself, but let's do it so other validators don't choke on it */
1805 addNSECRecordToLW(DNSName("*.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1806 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1807 return LWResult::Result::Success
;
1811 vector
<DNSRecord
> ret
;
1812 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1813 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1814 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1815 /* A + RRSIG, NSEC + RRSIG */
1816 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
1819 BOOST_AUTO_TEST_CASE(test_dnssec_validation_wildcard_expanded_onto_itself_nodata
)
1821 std::unique_ptr
<SyncRes
> sr
;
1824 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1827 const DNSName
target("*.powerdns.com.");
1830 auto luaconfsCopy
= g_luaconfs
.getCopy();
1831 luaconfsCopy
.dsAnchors
.clear();
1832 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1833 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1834 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1836 g_luaconfs
.setState(luaconfsCopy
);
1838 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 */) {
1839 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1840 if (domain
== target
) {
1841 const auto auth
= DNSName("powerdns.com.");
1842 /* we don't want a cut there */
1843 setLWResult(res
, 0, true, false, true);
1844 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1845 addRRSIG(keys
, res
->d_records
, auth
, 300);
1846 /* add a NSEC denying the DS */
1847 std::set
<uint16_t> types
= {QType::NSEC
};
1848 addNSECRecordToLW(domain
, DNSName("z") + domain
, types
, 600, res
->d_records
);
1849 addRRSIG(keys
, res
->d_records
, auth
, 300);
1850 return LWResult::Result::Success
;
1852 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1855 setLWResult(res
, 0, true, false, true);
1856 addRecordToLW(res
, domain
, QType::SOA
, "powerdns.com. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1857 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
1858 /* add the proof that the exact name does exist but that this type does not */
1859 addNSECRecordToLW(DNSName("*.powerdns.com."), DNSName("\\000.*.powerdns.com."), {QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1860 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1861 return LWResult::Result::Success
;
1865 vector
<DNSRecord
> ret
;
1866 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1867 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1868 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1869 /* SOA + RRSIG, NSEC + RRSIG */
1870 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
1873 BOOST_AUTO_TEST_CASE(test_dnssec_validation_wildcard_like_expanded_from_wildcard
)
1875 std::unique_ptr
<SyncRes
> sr
;
1878 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1881 const DNSName
target("*.sub.powerdns.com.");
1884 auto luaconfsCopy
= g_luaconfs
.getCopy();
1885 luaconfsCopy
.dsAnchors
.clear();
1886 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1887 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1888 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1890 g_luaconfs
.setState(luaconfsCopy
);
1892 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 */) {
1893 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1894 if (domain
== target
) {
1895 const auto auth
= DNSName("powerdns.com.");
1896 /* we don't want a cut there */
1897 setLWResult(res
, 0, true, false, true);
1898 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1899 addRRSIG(keys
, res
->d_records
, auth
, 300);
1900 addNSECRecordToLW(DNSName("*.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1901 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1902 return LWResult::Result::Success
;
1904 if (domain
== DNSName("sub.powerdns.com.")) {
1905 const auto auth
= DNSName("powerdns.com.");
1906 /* we don't want a cut there */
1907 setLWResult(res
, 0, true, false, true);
1908 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1909 addRRSIG(keys
, res
->d_records
, auth
, 300);
1910 /* add a NSEC denying the DS */
1911 addNSECRecordToLW(DNSName("*.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1912 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1913 return LWResult::Result::Success
;
1915 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
1918 setLWResult(res
, 0, true, false, true);
1919 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
1920 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300, false, boost::none
, DNSName("*.powerdns.com"));
1921 addNSECRecordToLW(DNSName("*.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
1922 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
1923 return LWResult::Result::Success
;
1927 vector
<DNSRecord
> ret
;
1928 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1929 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1930 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1931 /* A + RRSIG, NSEC + RRSIG */
1932 BOOST_REQUIRE_EQUAL(ret
.size(), 4U);
1936 BOOST_AUTO_TEST_CASE(test_dnssec_incomplete_cache_zonecut_qm
)
1938 std::unique_ptr
<SyncRes
> sr
;
1939 initSR(sr
, true, false);
1940 sr
->setQNameMinimization();
1941 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1946 auto luaconfsCopy
= g_luaconfs
.getCopy();
1947 luaconfsCopy
.dsAnchors
.clear();
1948 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1949 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1950 generateKeyMaterial(DNSName("net."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1951 generateKeyMaterial(DNSName("herokuapp.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1952 generateKeyMaterial(DNSName("nsone.net."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1953 g_luaconfs
.setState(luaconfsCopy
);
1955 size_t queriesCount
= 0;
1957 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 */) {
1960 DNSName
auth(domain
);
1961 DNSName
com("com.");
1962 DNSName
net("net.");
1963 DNSName
nsone("nsone.net.");
1964 DNSName
hero("herokuapp.com.");
1965 DNSName
p03nsone("dns1.p03.nsone.net.");
1967 // cerr << ip.toString() << ": " << domain << '|' << QType(type).toString() << endl;
1968 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
1969 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
1972 if (isRootServer(address
)) {
1973 if (domain
== com
) {
1974 setLWResult(res
, 0, false, false, true);
1975 addRecordToLW(res
, com
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 3600);
1976 addDS(com
, 300, res
->d_records
, keys
);
1977 addRRSIG(keys
, res
->d_records
, g_rootdnsname
, 300);
1978 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1980 else if (domain
== net
) {
1981 setLWResult(res
, 0, false, false, true);
1982 addRecordToLW(res
, net
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 3600);
1983 addDS(net
, 300, res
->d_records
, keys
);
1984 addRRSIG(keys
, res
->d_records
, g_rootdnsname
, 300);
1985 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1987 else if (domain
== p03nsone
&& type
== QType::A
) {
1988 setLWResult(res
, 0, false, false, true);
1989 addRecordToLW(res
, nsone
, QType::NS
, "dns1.p01.nsone.net.", DNSResourceRecord::AUTHORITY
, 3600);
1990 addNSECRecordToLW(nsone
, DNSName("zzz.nsone.net."), {QType::NS
, QType::SOA
, QType::RRSIG
, QType::DNSKEY
}, 600, res
->d_records
);
1991 addRRSIG(keys
, res
->d_records
, net
, 300);
1992 addRecordToLW(res
, "dns1.p01.nsone.net", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1997 return LWResult::Result::Success
;
2000 if (address
== ComboAddress("192.0.2.1:53")) {
2001 if (domain
== hero
&& type
== QType::NS
) {
2002 setLWResult(res
, 0, false, false, true);
2003 addRecordToLW(res
, hero
, QType::NS
, "dns1.p03.nsone.net.", DNSResourceRecord::AUTHORITY
, 3600);
2004 addDS(hero
, 300, res
->d_records
, keys
);
2005 addRRSIG(keys
, res
->d_records
, com
, 300);
2007 else if (domain
== nsone
&& type
== QType::A
) {
2008 setLWResult(res
, 0, false, false, true);
2009 addRecordToLW(res
, nsone
, QType::NS
, "dns1.p01.nsone.net.", DNSResourceRecord::AUTHORITY
, 3600);
2010 addNSECRecordToLW(nsone
, DNSName("zzz.nsone.net."), {QType::NS
, QType::SOA
, QType::RRSIG
, QType::DNSKEY
}, 600, res
->d_records
);
2011 addRRSIG(keys
, res
->d_records
, net
, 300);
2012 addRecordToLW(res
, "dns1.p01.nsone.net", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2017 return LWResult::Result::Success
;
2019 if (address
== ComboAddress("192.0.2.2:53")) {
2020 DNSName
p01("p01.nsone.net.");
2021 DNSName
p03("p03.nsone.net.");
2022 DNSName
p01nsone("dns1.p01.nsone.net.");
2023 if (domain
== hero
&& type
== QType::NS
) {
2024 setLWResult(res
, 0, true, false, true);
2025 addRecordToLW(res
, hero
, QType::NS
, "dns1.p03.nsone.net.", DNSResourceRecord::ANSWER
, 3600);
2026 addRRSIG(keys
, res
->d_records
, hero
, 300);
2028 else if (domain
== p01nsone
&& type
== QType::A
) {
2029 setLWResult(res
, 0, true, false, true);
2030 addRecordToLW(res
, p01nsone
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 3600);
2032 else if (domain
== p03nsone
&& type
== QType::A
) {
2033 setLWResult(res
, 0, true, false, true);
2034 addRecordToLW(res
, p03nsone
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 3600);
2036 else if (domain
== p01
&& type
== QType::A
) {
2037 setLWResult(res
, 0, true, false, true);
2038 addRecordToLW(res
, p01
, QType::SOA
, "dns1.p01.nsone.net. hostmaster.nsone.net. 123 43200 7200 1209600 10800", DNSResourceRecord::AUTHORITY
, 3600);
2040 else if (domain
== p03
&& type
== QType::A
) {
2041 setLWResult(res
, 0, true, false, true);
2042 addRecordToLW(res
, p03
, QType::SOA
, "dns1.p03.nsone.net. hostmaster.nsone.net. 123 43200 7200 1209600 10800", DNSResourceRecord::AUTHORITY
, 3600);
2047 return LWResult::Result::Success
;
2050 return LWResult::Result::Timeout
;
2053 vector
<DNSRecord
> ret
;
2054 int res
= sr
->beginResolve(DNSName("herokuapp.com."), QType(QType::NS
), QClass::IN
, ret
);
2055 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2056 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2057 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2058 BOOST_CHECK_EQUAL(queriesCount
, 8U);
2061 res
= sr
->beginResolve(DNSName("dns1.p03.nsone.net."), QType(QType::A
), QClass::IN
, ret
);
2062 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2063 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2064 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2065 BOOST_CHECK_EQUAL(queriesCount
, 14U);
2068 BOOST_AUTO_TEST_CASE(test_dnssec_secure_servfail_ds
)
2070 std::unique_ptr
<SyncRes
> sr
;
2073 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2076 const DNSName
target("powerdns.com.");
2077 const ComboAddress
targetAddr("192.0.2.42");
2080 auto luaconfsCopy
= g_luaconfs
.getCopy();
2081 luaconfsCopy
.dsAnchors
.clear();
2082 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2083 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2084 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2086 g_luaconfs
.setState(luaconfsCopy
);
2088 size_t queriesCount
= 0;
2090 /* make sure that the signature inception and validity times are computed
2091 based on the SyncRes time, not the current one, in case the function
2094 const time_t fixedNow
= sr
->getNow().tv_sec
;
2096 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 */) {
2099 DNSName auth
= domain
;
2100 if (domain
== target
) {
2101 auth
= DNSName("powerdns.com.");
2104 if (type
== QType::DS
&& domain
== DNSName("powerdns.com.")) {
2106 return LWResult::Result::Timeout
;
2109 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2110 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, true, fixedNow
);
2113 if (isRootServer(address
)) {
2114 setLWResult(res
, 0, false, false, true);
2115 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
2116 addDS(DNSName("com."), 300, res
->d_records
, keys
);
2117 addRRSIG(keys
, res
->d_records
, DNSName("."), 300, false, boost::none
, boost::none
, fixedNow
);
2118 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2119 return LWResult::Result::Success
;
2122 if (address
== ComboAddress("192.0.2.1:53")) {
2123 if (domain
== DNSName("com.")) {
2124 setLWResult(res
, 0, true, false, true);
2125 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
2126 addRRSIG(keys
, res
->d_records
, domain
, 300, false, boost::none
, boost::none
, fixedNow
);
2127 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2128 addRRSIG(keys
, res
->d_records
, domain
, 300);
2131 setLWResult(res
, 0, false, false, true);
2132 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
2133 /* do NOT include the DS here */
2134 //addDS(auth, 300, res->d_records, keys);
2135 //addRRSIG(keys, res->d_records, DNSName("com."), 300, false, boost::none, boost::none, fixedNow);
2136 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2138 return LWResult::Result::Success
;
2141 if (address
== ComboAddress("192.0.2.2:53")) {
2142 if (type
== QType::NS
) {
2143 setLWResult(res
, 0, true, false, true);
2144 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
2145 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
2146 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2147 addRRSIG(keys
, res
->d_records
, auth
, 300);
2150 setLWResult(res
, RCode::NoError
, true, false, true);
2151 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
2152 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
2154 return LWResult::Result::Success
;
2157 return LWResult::Result::Timeout
;
2160 vector
<DNSRecord
> ret
;
2162 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2165 catch (const ImmediateServFailException
& e
) {
2166 BOOST_CHECK(e
.reason
.find("Server Failure while retrieving DS records for powerdns.com") != string::npos
);
2169 /* and a second time to check nothing was cached */
2171 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2174 catch (const ImmediateServFailException
& e
) {
2175 BOOST_CHECK(e
.reason
.find("Server Failure while retrieving DS records for powerdns.com") != string::npos
);
2179 static void dnssec_secure_servfail_dnskey(DNSSECMode mode
, vState
/* expectedValidationResult */)
2181 std::unique_ptr
<SyncRes
> sr
;
2184 setDNSSECValidation(sr
, mode
);
2187 const DNSName
target("powerdns.com.");
2188 const ComboAddress
targetAddr("192.0.2.42");
2191 auto luaconfsCopy
= g_luaconfs
.getCopy();
2192 luaconfsCopy
.dsAnchors
.clear();
2193 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2194 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2195 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2197 g_luaconfs
.setState(luaconfsCopy
);
2199 size_t queriesCount
= 0;
2201 /* make sure that the signature inception and validity times are computed
2202 based on the SyncRes time, not the current one, in case the function
2205 const time_t fixedNow
= sr
->getNow().tv_sec
;
2207 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 */) {
2210 DNSName auth
= domain
;
2211 if (domain
== target
) {
2212 auth
= DNSName("powerdns.com.");
2215 if (type
== QType::DNSKEY
&& domain
== DNSName("powerdns.com.")) {
2217 return LWResult::Result::Timeout
;
2220 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2221 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, true, fixedNow
);
2224 if (isRootServer(address
)) {
2225 setLWResult(res
, 0, false, false, true);
2226 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
2227 addDS(DNSName("com."), 300, res
->d_records
, keys
);
2228 addRRSIG(keys
, res
->d_records
, DNSName("."), 300, false, boost::none
, boost::none
, fixedNow
);
2229 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2230 return LWResult::Result::Success
;
2233 if (address
== ComboAddress("192.0.2.1:53")) {
2234 if (domain
== DNSName("com.")) {
2235 setLWResult(res
, 0, true, false, true);
2236 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
2237 addRRSIG(keys
, res
->d_records
, domain
, 300, false, boost::none
, boost::none
, fixedNow
);
2238 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2239 addRRSIG(keys
, res
->d_records
, domain
, 300);
2242 setLWResult(res
, 0, false, false, true);
2243 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
2244 addDS(auth
, 300, res
->d_records
, keys
);
2245 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300, false, boost::none
, boost::none
, fixedNow
);
2246 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2248 return LWResult::Result::Success
;
2251 if (address
== ComboAddress("192.0.2.2:53")) {
2252 if (type
== QType::NS
) {
2253 setLWResult(res
, 0, true, false, true);
2254 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
2255 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
2256 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2257 addRRSIG(keys
, res
->d_records
, auth
, 300);
2260 setLWResult(res
, RCode::NoError
, true, false, true);
2261 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
2262 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
2264 return LWResult::Result::Success
;
2267 return LWResult::Result::Timeout
;
2270 vector
<DNSRecord
> ret
;
2272 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2275 catch (const ImmediateServFailException
& e
) {
2276 BOOST_CHECK(e
.reason
.find("Server Failure while retrieving DNSKEY records for powerdns.com") != string::npos
);
2279 /* and a second time to check nothing was cached */
2281 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2284 catch (const ImmediateServFailException
& e
) {
2285 BOOST_CHECK(e
.reason
.find("Server Failure while retrieving DNSKEY records for powerdns.com") != string::npos
);
2289 BOOST_AUTO_TEST_CASE(test_dnssec_secure_servfail_dnskey
)
2291 dnssec_secure_servfail_dnskey(DNSSECMode::ValidateAll
, vState::Indeterminate
);
2292 dnssec_secure_servfail_dnskey(DNSSECMode::Off
, vState::Indeterminate
);
2295 // Same test as above but powerdns.com is now Insecure according to parent, so failure to retrieve DNSSKEYs
2296 // should be mostly harmless.
2297 static void dnssec_secure_servfail_dnskey_insecure(DNSSECMode mode
, vState expectedValidationResult
)
2299 std::unique_ptr
<SyncRes
> sr
;
2302 setDNSSECValidation(sr
, mode
);
2305 const DNSName
target("powerdns.com.");
2306 const ComboAddress
targetAddr("192.0.2.42");
2308 // We use two sets of keys, as powerdns.com is Insecure according to parent but returns signed results,
2309 // triggering a (failing) DNSKEY retrieval.
2311 testkeysset_t pdnskeys
;
2313 auto luaconfsCopy
= g_luaconfs
.getCopy();
2314 luaconfsCopy
.dsAnchors
.clear();
2315 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2316 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2317 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, pdnskeys
);
2319 g_luaconfs
.setState(luaconfsCopy
);
2321 size_t queriesCount
= 0;
2323 /* make sure that the signature inception and validity times are computed
2324 based on the SyncRes time, not the current one, in case the function
2327 const time_t fixedNow
= sr
->getNow().tv_sec
;
2329 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 */) {
2332 DNSName auth
= domain
;
2333 if (domain
== target
) {
2334 auth
= DNSName("powerdns.com.");
2337 if (type
== QType::DNSKEY
&& domain
== DNSName("powerdns.com.")) {
2339 return LWResult::Result::Timeout
;
2342 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2343 // This one does not know about pdnskeys, so it will declare powerdns.com as Insecure
2344 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, true, fixedNow
);
2347 if (isRootServer(address
)) {
2348 setLWResult(res
, 0, false, false, true);
2349 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
2350 addDS(DNSName("com."), 300, res
->d_records
, keys
);
2351 addRRSIG(keys
, res
->d_records
, DNSName("."), 300, false, boost::none
, boost::none
, fixedNow
);
2352 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2353 return LWResult::Result::Success
;
2356 if (address
== ComboAddress("192.0.2.1:53")) {
2357 if (domain
== DNSName("com.")) {
2358 setLWResult(res
, 0, true, false, true);
2359 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
2360 addRRSIG(keys
, res
->d_records
, domain
, 300, false, boost::none
, boost::none
, fixedNow
);
2361 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2362 addRRSIG(keys
, res
->d_records
, domain
, 300);
2365 setLWResult(res
, 0, false, false, true);
2366 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
2367 addDS(auth
, 300, res
->d_records
, keys
);
2368 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300, false, boost::none
, boost::none
, fixedNow
);
2369 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2371 return LWResult::Result::Success
;
2374 if (address
== ComboAddress("192.0.2.2:53")) {
2375 if (type
== QType::NS
) {
2376 setLWResult(res
, 0, true, false, true);
2377 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
2378 addRRSIG(pdnskeys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
2379 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2380 addRRSIG(pdnskeys
, res
->d_records
, auth
, 300);
2383 setLWResult(res
, RCode::NoError
, true, false, true);
2384 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
2385 addRRSIG(pdnskeys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, fixedNow
);
2387 return LWResult::Result::Success
;
2390 return LWResult::Result::Timeout
;
2393 vector
<DNSRecord
> ret
;
2394 auto res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2395 BOOST_CHECK_EQUAL(res
, 0);
2396 BOOST_CHECK_EQUAL(sr
->getValidationState(), expectedValidationResult
);
2397 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2400 BOOST_AUTO_TEST_CASE(test_dnssec_secure_servfail_dnskey_insecure
)
2402 dnssec_secure_servfail_dnskey_insecure(DNSSECMode::ValidateAll
, vState::Insecure
);
2403 dnssec_secure_servfail_dnskey_insecure(DNSSECMode::Off
, vState::Insecure
);
2406 BOOST_AUTO_TEST_SUITE_END()