1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3 #include <boost/test/unit_test.hpp>
5 #include "arguments.hh"
6 #include "dnssecinfra.hh"
7 #include "dnsseckeeper.hh"
8 #include "lua-recursor4.hh"
9 #include "namespaces.hh"
10 #include "rec-lua-conf.hh"
11 #include "root-dnssec.hh"
13 #include "test-common.hh"
15 #include "validate-recursor.hh"
17 RecursorStats g_stats
;
18 GlobalStateHolder
<LuaConfigItems
> g_luaconfs
;
19 thread_local
std::unique_ptr
<MemRecursorCache
> t_RC
{nullptr};
20 unsigned int g_numThreads
= 1;
22 /* Fake some required functions we didn't want the trouble to
26 static ArgvMap theArg
;
35 bool RecursorLua4::preoutquery(const ComboAddress
& ns
, const ComboAddress
& requestor
, const DNSName
& query
, const QType
& qtype
, bool isTcp
, vector
<DNSRecord
>& res
, int& ret
)
40 int asyncresolve(const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
)
45 /* primeHints() is only here for now because it
46 was way too much trouble to link with the real one.
47 We should fix this, empty functions are one thing, but this is
51 #include "root-addresses.hh"
55 vector
<DNSRecord
> nsset
;
57 t_RC
= std::unique_ptr
<MemRecursorCache
>(new MemRecursorCache());
59 DNSRecord arr
, aaaarr
, nsrr
;
60 nsrr
.d_name
=g_rootdnsname
;
62 aaaarr
.d_type
=QType::AAAA
;
63 nsrr
.d_type
=QType::NS
;
64 arr
.d_ttl
=aaaarr
.d_ttl
=nsrr
.d_ttl
=time(nullptr)+3600000;
66 for(char c
='a';c
<='m';++c
) {
67 static char templ
[40];
68 strncpy(templ
,"a.root-servers.net.", sizeof(templ
) - 1);
69 templ
[sizeof(templ
)-1] = '\0';
71 aaaarr
.d_name
=arr
.d_name
=DNSName(templ
);
72 nsrr
.d_content
=std::make_shared
<NSRecordContent
>(DNSName(templ
));
73 arr
.d_content
=std::make_shared
<ARecordContent
>(ComboAddress(rootIps4
[c
-'a']));
74 vector
<DNSRecord
> aset
;
76 t_RC
->replace(time(0), DNSName(templ
), QType(QType::A
), aset
, vector
<std::shared_ptr
<RRSIGRecordContent
>>(), vector
<std::shared_ptr
<DNSRecord
>>(), true); // auth, nuke it all
77 if (rootIps6
[c
-'a'] != NULL
) {
78 aaaarr
.d_content
=std::make_shared
<AAAARecordContent
>(ComboAddress(rootIps6
[c
-'a']));
80 vector
<DNSRecord
> aaaaset
;
81 aaaaset
.push_back(aaaarr
);
82 t_RC
->replace(time(0), DNSName(templ
), QType(QType::AAAA
), aaaaset
, vector
<std::shared_ptr
<RRSIGRecordContent
>>(), vector
<std::shared_ptr
<DNSRecord
>>(), true);
85 nsset
.push_back(nsrr
);
87 t_RC
->replace(time(0), g_rootdnsname
, QType(QType::NS
), nsset
, vector
<std::shared_ptr
<RRSIGRecordContent
>>(), vector
<std::shared_ptr
<DNSRecord
>>(), false); // and stuff in the cache
90 LuaConfigItems::LuaConfigItems()
92 for (const auto &dsRecord
: rootDSs
) {
93 auto ds
=unique_ptr
<DSRecordContent
>(dynamic_cast<DSRecordContent
*>(DSRecordContent::make(dsRecord
)));
94 dsAnchors
[g_rootdnsname
].insert(*ds
);
98 /* Some helpers functions */
100 static void init(bool debug
=false)
104 L
.setLoglevel((Logger::Urgency
)(6)); // info and up
105 L
.disableSyslog(true);
106 L
.toConsole(Logger::Info
);
109 seedRandom("/dev/urandom");
112 t_RC
= std::unique_ptr
<MemRecursorCache
>(new MemRecursorCache());
114 SyncRes::s_maxqperq
= 50;
115 SyncRes::s_maxtotusec
= 1000*7000;
116 SyncRes::s_maxdepth
= 40;
117 SyncRes::s_maxnegttl
= 3600;
118 SyncRes::s_maxcachettl
= 86400;
119 SyncRes::s_packetcachettl
= 3600;
120 SyncRes::s_packetcacheservfailttl
= 60;
121 SyncRes::s_serverdownmaxfails
= 64;
122 SyncRes::s_serverdownthrottletime
= 60;
123 SyncRes::s_doIPv6
= true;
124 SyncRes::s_ecsipv4limit
= 24;
125 SyncRes::s_ecsipv6limit
= 56;
126 SyncRes::s_rootNXTrust
= true;
127 SyncRes::s_minimumTTL
= 0;
128 SyncRes::s_serverID
= "PowerDNS Unit Tests Server ID";
129 SyncRes::clearEDNSSubnets();
130 SyncRes::clearEDNSDomains();
131 SyncRes::clearDelegationOnly();
132 SyncRes::clearDontQuery();
134 SyncRes::clearNSSpeeds();
135 BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0);
136 SyncRes::clearEDNSStatuses();
137 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0);
138 SyncRes::clearThrottle();
139 BOOST_CHECK_EQUAL(SyncRes::getThrottledServersSize(), 0);
140 SyncRes::clearFailedServers();
141 BOOST_CHECK_EQUAL(SyncRes::getFailedServersSize(), 0);
143 auto luaconfsCopy
= g_luaconfs
.getCopy();
144 luaconfsCopy
.dfe
.clear();
145 luaconfsCopy
.dsAnchors
.clear();
146 for (const auto &dsRecord
: rootDSs
) {
147 auto ds
=unique_ptr
<DSRecordContent
>(dynamic_cast<DSRecordContent
*>(DSRecordContent::make(dsRecord
)));
148 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(*ds
);
150 luaconfsCopy
.negAnchors
.clear();
151 g_luaconfs
.setState(luaconfsCopy
);
153 g_dnssecmode
= DNSSECMode::Off
;
156 ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Unit Tests";
159 static void initSR(std::unique_ptr
<SyncRes
>& sr
, bool dnssec
=false, bool debug
=false, time_t fakeNow
=0)
163 now
.tv_sec
= fakeNow
;
167 Utility::gettimeofday(&now
, 0);
172 sr
= std::unique_ptr
<SyncRes
>(new SyncRes(now
));
173 sr
->setDoEDNS0(true);
175 sr
->setDoDNSSEC(dnssec
);
178 sr
->setLogMode(debug
== false ? SyncRes::LogNone
: SyncRes::Log
);
180 SyncRes::setDomainMap(std::make_shared
<SyncRes::domainmap_t
>());
181 SyncRes::clearNegCache();
184 static void setDNSSECValidation(std::unique_ptr
<SyncRes
>& sr
, const DNSSECMode
& mode
)
186 sr
->setDNSSECValidationRequested(true);
190 static void setLWResult(LWResult
* res
, int rcode
, bool aa
=false, bool tc
=false, bool edns
=false)
192 res
->d_rcode
= rcode
;
195 res
->d_haveEDNS
= edns
;
198 static void addRecordToLW(LWResult
* res
, const DNSName
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
=DNSResourceRecord::ANSWER
, uint32_t ttl
=60)
200 addRecordToList(res
->d_records
, name
, type
, content
, place
, ttl
);
203 static void addRecordToLW(LWResult
* res
, const std::string
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
=DNSResourceRecord::ANSWER
, uint32_t ttl
=60)
205 addRecordToLW(res
, DNSName(name
), type
, content
, place
, ttl
);
208 static bool isRootServer(const ComboAddress
& ip
)
211 for (size_t idx
= 0; idx
< rootIps4Count
; idx
++) {
212 if (ip
.toString() == rootIps4
[idx
]) {
218 for (size_t idx
= 0; idx
< rootIps6Count
; idx
++) {
219 if (ip
.toString() == rootIps6
[idx
]) {
228 static void computeRRSIG(const DNSSECPrivateKey
& dpk
, const DNSName
& signer
, const DNSName
& signQName
, uint16_t signQType
, uint32_t signTTL
, uint32_t sigValidity
, RRSIGRecordContent
& rrc
, vector
<shared_ptr
<DNSRecordContent
> >& toSign
, boost::optional
<uint8_t> algo
=boost::none
, boost::optional
<uint32_t> inception
=boost::none
)
230 time_t now
= time(nullptr);
231 DNSKEYRecordContent drc
= dpk
.getDNSKEY();
232 const std::shared_ptr
<DNSCryptoKeyEngine
> rc
= dpk
.getKey();
234 rrc
.d_type
= signQType
;
235 rrc
.d_labels
= signQName
.countLabels() - signQName
.isWildcard();
236 rrc
.d_originalttl
= signTTL
;
237 rrc
.d_siginception
= inception
? *inception
: (now
- 10);
238 rrc
.d_sigexpire
= now
+ sigValidity
;
239 rrc
.d_signer
= signer
;
241 rrc
.d_tag
= drc
.getTag();
242 rrc
.d_algorithm
= algo
? *algo
: drc
.d_algorithm
;
244 std::string msg
= getMessageForRRSET(signQName
, rrc
, toSign
);
246 rrc
.d_signature
= rc
->sign(msg
);
249 typedef std::unordered_map
<DNSName
, std::pair
<DNSSECPrivateKey
, DSRecordContent
> > testkeysset_t
;
251 static void addRRSIG(const testkeysset_t
& keys
, std::vector
<DNSRecord
>& records
, const DNSName
& signer
, uint32_t sigValidity
, bool broken
=false, boost::optional
<uint8_t> algo
=boost::none
, boost::optional
<DNSName
> wildcard
=boost::none
)
253 if (records
.empty()) {
257 const auto it
= keys
.find(signer
);
258 if (it
== keys
.cend()) {
259 throw std::runtime_error("No DNSKEY found for " + signer
.toString() + ", unable to compute the requested RRSIG");
262 size_t recordsCount
= records
.size();
263 const DNSName
& name
= records
[recordsCount
-1].d_name
;
264 const uint16_t type
= records
[recordsCount
-1].d_type
;
266 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
267 for (const auto record
: records
) {
268 if (record
.d_name
== name
&& record
.d_type
== type
) {
269 recordcontents
.push_back(record
.d_content
);
273 RRSIGRecordContent rrc
;
274 computeRRSIG(it
->second
.first
, signer
, wildcard
? *wildcard
: records
[recordsCount
-1].d_name
, records
[recordsCount
-1].d_type
, records
[recordsCount
-1].d_ttl
, sigValidity
, rrc
, recordcontents
, algo
);
276 rrc
.d_signature
[0] ^= 42;
280 rec
.d_place
= records
[recordsCount
-1].d_place
;
281 rec
.d_name
= records
[recordsCount
-1].d_name
;
282 rec
.d_type
= QType::RRSIG
;
283 rec
.d_ttl
= sigValidity
;
285 rec
.d_content
= std::make_shared
<RRSIGRecordContent
>(rrc
);
286 records
.push_back(rec
);
289 static void addDNSKEY(const testkeysset_t
& keys
, const DNSName
& signer
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
291 const auto it
= keys
.find(signer
);
292 if (it
== keys
.cend()) {
293 throw std::runtime_error("No DNSKEY found for " + signer
.toString());
297 rec
.d_place
= DNSResourceRecord::ANSWER
;
299 rec
.d_type
= QType::DNSKEY
;
302 rec
.d_content
= std::make_shared
<DNSKEYRecordContent
>(it
->second
.first
.getDNSKEY());
303 records
.push_back(rec
);
306 static void addDS(const DNSName
& domain
, uint32_t ttl
, std::vector
<DNSRecord
>& records
, const testkeysset_t
& keys
, DNSResourceRecord::Place place
=DNSResourceRecord::AUTHORITY
)
308 const auto it
= keys
.find(domain
);
309 if (it
== keys
.cend()) {
315 rec
.d_type
= QType::DS
;
318 rec
.d_content
= std::make_shared
<DSRecordContent
>(it
->second
.second
);
320 records
.push_back(rec
);
323 static void addNSECRecordToLW(const DNSName
& domain
, const DNSName
& next
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
325 NSECRecordContent nrc
;
332 rec
.d_type
= QType::NSEC
;
333 rec
.d_content
= std::make_shared
<NSECRecordContent
>(nrc
);
334 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
336 records
.push_back(rec
);
339 static void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
)
341 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(algo
));
342 dcke
->create((algo
<= 10) ? 2048 : dcke
->getBits());
343 DNSSECPrivateKey dpk
;
346 DSRecordContent ds
= makeDSFromDNSKey(name
, dpk
.getDNSKEY(), digest
);
347 keys
[name
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
,ds
);
350 static void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
, map
<DNSName
,dsmap_t
>& dsAnchors
)
352 generateKeyMaterial(name
, algo
, digest
, keys
);
353 dsAnchors
[name
].insert(keys
[name
].second
);
358 BOOST_AUTO_TEST_SUITE(syncres_cc
)
360 BOOST_AUTO_TEST_CASE(test_root_primed
) {
361 std::unique_ptr
<SyncRes
> sr
;
366 const DNSName
target("a.root-servers.net.");
368 /* we are primed, we should be able to resolve A a.root-servers.net. without any query */
369 vector
<DNSRecord
> ret
;
370 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
371 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
372 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
373 BOOST_CHECK(ret
[0].d_type
== QType::A
);
374 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
377 res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
378 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
379 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
380 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
381 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
382 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
385 BOOST_AUTO_TEST_CASE(test_root_primed_ns
) {
386 std::unique_ptr
<SyncRes
> sr
;
390 const DNSName
target(".");
392 /* we are primed, but we should not be able to NS . without any query
393 because the . NS entry is not stored as authoritative */
395 size_t queriesCount
= 0;
397 sr
->setAsyncCallback([target
,&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
400 if (domain
== target
&& type
== QType::NS
) {
402 setLWResult(res
, 0, true, false, true);
403 char addr
[] = "a.root-servers.net.";
404 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
406 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
409 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
410 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
418 vector
<DNSRecord
> ret
;
419 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
420 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
421 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
422 BOOST_CHECK_EQUAL(queriesCount
, 1);
425 BOOST_AUTO_TEST_CASE(test_root_not_primed
) {
426 std::unique_ptr
<SyncRes
> sr
;
429 size_t queriesCount
= 0;
431 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
434 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
435 setLWResult(res
, 0, true, false, true);
436 addRecordToLW(res
, g_rootdnsname
, QType::NS
, "a.root-servers.net.", DNSResourceRecord::ANSWER
, 3600);
437 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
438 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
446 /* we are not primed yet, so SyncRes will have to call primeHints()
447 then call getRootNS(), for which at least one of the root servers needs to answer */
448 vector
<DNSRecord
> ret
;
449 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
450 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
451 BOOST_CHECK_EQUAL(ret
.size(), 1);
452 BOOST_CHECK_EQUAL(queriesCount
, 2);
455 BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response
) {
456 std::unique_ptr
<SyncRes
> sr
;
458 std::set
<ComboAddress
> downServers
;
460 /* we are not primed yet, so SyncRes will have to call primeHints()
461 then call getRootNS(), for which at least one of the root servers needs to answer.
462 None will, so it should ServFail.
464 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
466 downServers
.insert(ip
);
470 vector
<DNSRecord
> ret
;
471 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
472 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
473 BOOST_CHECK_EQUAL(ret
.size(), 0);
474 BOOST_CHECK(downServers
.size() > 0);
475 /* we explicitly refuse to mark the root servers down */
476 for (const auto& server
: downServers
) {
477 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
481 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback
) {
482 std::unique_ptr
<SyncRes
> sr
;
485 ComboAddress noEDNSServer
;
486 size_t queriesWithEDNS
= 0;
487 size_t queriesWithoutEDNS
= 0;
489 sr
->setAsyncCallback([&queriesWithEDNS
, &queriesWithoutEDNS
, &noEDNSServer
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
490 if (EDNS0Level
!= 0) {
494 setLWResult(res
, RCode::FormErr
);
498 queriesWithoutEDNS
++;
500 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
501 setLWResult(res
, 0, true, false, false);
502 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
511 /* fake that the root NS doesn't handle EDNS, check that we fallback */
512 vector
<DNSRecord
> ret
;
513 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
514 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
515 BOOST_CHECK_EQUAL(ret
.size(), 1);
516 BOOST_CHECK_EQUAL(queriesWithEDNS
, 1);
517 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 1);
518 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 1);
519 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer
), SyncRes::EDNSStatus::NOEDNS
);
522 BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback
) {
523 std::unique_ptr
<SyncRes
> sr
;
526 size_t queriesWithEDNS
= 0;
527 size_t queriesWithoutEDNS
= 0;
529 sr
->setAsyncCallback([&queriesWithEDNS
, &queriesWithoutEDNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
530 if (EDNS0Level
!= 0) {
532 setLWResult(res
, RCode::NotImp
);
536 queriesWithoutEDNS
++;
538 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
539 setLWResult(res
, 0, true, false, false);
540 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
549 /* fake that the NS doesn't handle EDNS, check that we fallback */
550 vector
<DNSRecord
> ret
;
551 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
552 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
553 BOOST_CHECK_EQUAL(ret
.size(), 1);
554 BOOST_CHECK_EQUAL(queriesWithEDNS
, 1);
555 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 1);
558 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
) {
559 std::unique_ptr
<SyncRes
> sr
;
562 sr
->setAsyncCallback([](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
564 setLWResult(res
, 0, false, true, false);
567 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
568 setLWResult(res
, 0, true, false, false);
569 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
578 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
579 vector
<DNSRecord
> ret
;
580 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
581 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
584 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
) {
585 std::unique_ptr
<SyncRes
> sr
;
588 size_t tcpQueriesCount
= 0;
590 sr
->setAsyncCallback([&tcpQueriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
592 setLWResult(res
, 0, true, true, false);
596 /* first TCP query is answered with a TC response */
598 if (tcpQueriesCount
== 1) {
599 setLWResult(res
, 0, true, true, false);
602 setLWResult(res
, 0, true, false, false);
605 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
611 vector
<DNSRecord
> ret
;
612 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
613 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
614 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2);
617 BOOST_AUTO_TEST_CASE(test_all_nss_down
) {
618 std::unique_ptr
<SyncRes
> sr
;
620 std::set
<ComboAddress
> downServers
;
624 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
626 if (isRootServer(ip
)) {
627 setLWResult(res
, 0, false, false, true);
628 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
629 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
630 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
633 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
634 setLWResult(res
, 0, false, false, true);
635 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
636 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
637 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
638 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
639 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
640 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
644 downServers
.insert(ip
);
649 DNSName
target("powerdns.com.");
651 vector
<DNSRecord
> ret
;
652 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
653 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
654 BOOST_CHECK_EQUAL(ret
.size(), 0);
655 BOOST_CHECK_EQUAL(downServers
.size(), 4);
657 for (const auto& server
: downServers
) {
658 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
659 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
663 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
) {
664 std::unique_ptr
<SyncRes
> sr
;
666 std::set
<ComboAddress
> downServers
;
670 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
672 if (isRootServer(ip
)) {
673 setLWResult(res
, 0, false, false, true);
674 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
675 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
676 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
679 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
680 setLWResult(res
, 0, false, false, true);
681 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
682 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
683 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
684 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
685 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
686 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
690 downServers
.insert(ip
);
695 /* exact same test than the previous one, except instead of a time out we fake a network error */
696 DNSName
target("powerdns.com.");
698 vector
<DNSRecord
> ret
;
699 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
700 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
701 BOOST_CHECK_EQUAL(ret
.size(), 0);
702 BOOST_CHECK_EQUAL(downServers
.size(), 4);
704 for (const auto& server
: downServers
) {
705 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
706 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
711 BOOST_AUTO_TEST_CASE(test_os_limit_errors
) {
712 std::unique_ptr
<SyncRes
> sr
;
714 std::set
<ComboAddress
> downServers
;
718 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
720 if (isRootServer(ip
)) {
721 setLWResult(res
, 0, false, false, true);
722 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
723 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
724 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
727 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
728 setLWResult(res
, 0, false, false, true);
729 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
730 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
731 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
732 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
733 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
734 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
738 if (downServers
.size() < 3) {
739 /* only the last one will answer */
740 downServers
.insert(ip
);
744 setLWResult(res
, 0, true, false, true);
745 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
751 DNSName
target("powerdns.com.");
753 vector
<DNSRecord
> ret
;
754 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
755 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
756 BOOST_CHECK_EQUAL(ret
.size(), 1);
757 BOOST_CHECK_EQUAL(downServers
.size(), 3);
759 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
760 for (const auto& server
: downServers
) {
761 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
762 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
766 BOOST_AUTO_TEST_CASE(test_glued_referral
) {
767 std::unique_ptr
<SyncRes
> sr
;
772 const DNSName
target("powerdns.com.");
774 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
775 /* this will cause issue with qname minimization if we ever implement it */
776 if (domain
!= target
) {
780 if (isRootServer(ip
)) {
781 setLWResult(res
, 0, false, false, true);
782 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
783 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
784 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
787 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
788 setLWResult(res
, 0, false, false, true);
789 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
790 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
791 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
792 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
793 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
794 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
797 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
798 setLWResult(res
, 0, true, false, true);
799 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
807 vector
<DNSRecord
> ret
;
808 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
809 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
810 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
811 BOOST_CHECK(ret
[0].d_type
== QType::A
);
812 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
815 BOOST_AUTO_TEST_CASE(test_glueless_referral
) {
816 std::unique_ptr
<SyncRes
> sr
;
821 const DNSName
target("powerdns.com.");
823 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
825 if (isRootServer(ip
)) {
826 setLWResult(res
, 0, false, false, true);
828 if (domain
.isPartOf(DNSName("com."))) {
829 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
830 } else if (domain
.isPartOf(DNSName("org."))) {
831 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
834 setLWResult(res
, RCode::NXDomain
, false, false, true);
838 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
839 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
842 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
843 if (domain
== target
) {
844 setLWResult(res
, 0, false, false, true);
845 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
846 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
849 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
850 setLWResult(res
, 0, true, false, true);
851 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
852 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
855 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
856 setLWResult(res
, 0, true, false, true);
857 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
858 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
862 setLWResult(res
, RCode::NXDomain
, false, false, true);
865 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
866 setLWResult(res
, 0, true, false, true);
867 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
875 vector
<DNSRecord
> ret
;
876 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
877 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
878 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
879 BOOST_CHECK(ret
[0].d_type
== QType::A
);
880 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
883 BOOST_AUTO_TEST_CASE(test_edns_submask_by_domain
) {
884 std::unique_ptr
<SyncRes
> sr
;
889 const DNSName
target("powerdns.com.");
890 SyncRes::addEDNSDomain(target
);
892 EDNSSubnetOpts incomingECS
;
893 incomingECS
.source
= Netmask("192.0.2.128/32");
894 sr
->setIncomingECSFound(true);
895 sr
->setIncomingECS(incomingECS
);
897 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
899 BOOST_REQUIRE(srcmask
);
900 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
904 vector
<DNSRecord
> ret
;
905 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
906 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
909 BOOST_AUTO_TEST_CASE(test_edns_submask_by_addr
) {
910 std::unique_ptr
<SyncRes
> sr
;
915 const DNSName
target("powerdns.com.");
916 SyncRes::addEDNSSubnet(Netmask("192.0.2.1/32"));
918 EDNSSubnetOpts incomingECS
;
919 incomingECS
.source
= Netmask("2001:DB8::FF/128");
920 sr
->setIncomingECSFound(true);
921 sr
->setIncomingECS(incomingECS
);
923 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
925 if (isRootServer(ip
)) {
926 BOOST_REQUIRE(!srcmask
);
928 setLWResult(res
, 0, false, false, true);
929 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
930 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
932 } else if (ip
== ComboAddress("192.0.2.1:53")) {
934 BOOST_REQUIRE(srcmask
);
935 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
937 setLWResult(res
, 0, true, false, false);
938 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
945 vector
<DNSRecord
> ret
;
946 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
947 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
948 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
949 BOOST_CHECK(ret
[0].d_type
== QType::A
);
950 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
953 BOOST_AUTO_TEST_CASE(test_following_cname
) {
954 std::unique_ptr
<SyncRes
> sr
;
959 const DNSName
target("cname.powerdns.com.");
960 const DNSName
cnameTarget("cname-target.powerdns.com");
962 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
964 if (isRootServer(ip
)) {
965 setLWResult(res
, 0, false, false, true);
966 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
967 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
969 } else if (ip
== ComboAddress("192.0.2.1:53")) {
971 if (domain
== target
) {
972 setLWResult(res
, 0, true, false, false);
973 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
976 else if (domain
== cnameTarget
) {
977 setLWResult(res
, 0, true, false, false);
978 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
987 vector
<DNSRecord
> ret
;
988 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
989 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
990 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
991 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
992 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
993 BOOST_CHECK(ret
[1].d_type
== QType::A
);
994 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
997 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
) {
998 std::unique_ptr
<SyncRes
> sr
;
1003 /* In this test we directly get the NS server for cname.powerdns.com.,
1004 and we don't know whether it's also authoritative for
1005 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1006 the additional A record for cname-target.powerdns.com. */
1007 const DNSName
target("cname.powerdns.com.");
1008 const DNSName
cnameTarget("cname-target.powerdns.com");
1010 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1012 if (isRootServer(ip
)) {
1014 setLWResult(res
, 0, false, false, true);
1016 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1017 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1019 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1021 if (domain
== target
) {
1022 setLWResult(res
, 0, true, false, false);
1023 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1024 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1026 } else if (domain
== cnameTarget
) {
1027 setLWResult(res
, 0, true, false, false);
1028 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1038 vector
<DNSRecord
> ret
;
1039 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1040 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1041 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1042 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1043 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1044 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1045 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1046 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1047 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1050 BOOST_AUTO_TEST_CASE(test_cname_loop
) {
1051 std::unique_ptr
<SyncRes
> sr
;
1057 const DNSName
target("cname.powerdns.com.");
1059 sr
->setAsyncCallback([target
,&count
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1063 if (isRootServer(ip
)) {
1065 setLWResult(res
, 0, false, false, true);
1066 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1067 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1069 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1071 if (domain
== target
) {
1072 setLWResult(res
, 0, true, false, false);
1073 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1083 vector
<DNSRecord
> ret
;
1084 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1085 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1086 BOOST_CHECK_GT(ret
.size(), 0);
1087 BOOST_CHECK_EQUAL(count
, 2);
1090 BOOST_AUTO_TEST_CASE(test_cname_depth
) {
1091 std::unique_ptr
<SyncRes
> sr
;
1097 const DNSName
target("cname.powerdns.com.");
1099 sr
->setAsyncCallback([target
,&depth
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1101 if (isRootServer(ip
)) {
1103 setLWResult(res
, 0, false, false, true);
1104 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1105 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1107 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1109 setLWResult(res
, 0, true, false, false);
1110 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(depth
) + "-cname.powerdns.com");
1118 vector
<DNSRecord
> ret
;
1119 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1120 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1121 BOOST_CHECK_EQUAL(ret
.size(), depth
);
1122 /* we have an arbitrary limit at 10 when following a CNAME chain */
1123 BOOST_CHECK_EQUAL(depth
, 10 + 2);
1126 BOOST_AUTO_TEST_CASE(test_time_limit
) {
1127 std::unique_ptr
<SyncRes
> sr
;
1133 const DNSName
target("cname.powerdns.com.");
1135 sr
->setAsyncCallback([target
,&queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1139 if (isRootServer(ip
)) {
1140 setLWResult(res
, 0, false, false, true);
1141 /* Pretend that this query took 2000 ms */
1144 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1145 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1147 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1149 setLWResult(res
, 0, true, false, false);
1150 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1157 /* Set the maximum time to 1 ms */
1158 SyncRes::s_maxtotusec
= 1000;
1161 vector
<DNSRecord
> ret
;
1162 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1165 catch(const ImmediateServFailException
& e
) {
1167 BOOST_CHECK_EQUAL(queries
, 1);
1170 BOOST_AUTO_TEST_CASE(test_referral_depth
) {
1171 std::unique_ptr
<SyncRes
> sr
;
1177 const DNSName
target("www.powerdns.com.");
1179 sr
->setAsyncCallback([target
,&queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1183 if (isRootServer(ip
)) {
1184 setLWResult(res
, 0, false, false, true);
1186 if (domain
== DNSName("www.powerdns.com.")) {
1187 addRecordToLW(res
, domain
, QType::NS
, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1189 else if (domain
== DNSName("ns.powerdns.com.")) {
1190 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1192 else if (domain
== DNSName("ns1.powerdns.org.")) {
1193 addRecordToLW(res
, domain
, QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1195 else if (domain
== DNSName("ns2.powerdns.org.")) {
1196 addRecordToLW(res
, domain
, QType::NS
, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1198 else if (domain
== DNSName("ns3.powerdns.org.")) {
1199 addRecordToLW(res
, domain
, QType::NS
, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1201 else if (domain
== DNSName("ns4.powerdns.org.")) {
1202 addRecordToLW(res
, domain
, QType::NS
, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1203 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::AUTHORITY
, 172800);
1207 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1209 setLWResult(res
, 0, true, false, false);
1210 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1217 /* Set the maximum depth low */
1218 SyncRes::s_maxdepth
= 10;
1221 vector
<DNSRecord
> ret
;
1222 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1225 catch(const ImmediateServFailException
& e
) {
1229 BOOST_AUTO_TEST_CASE(test_cname_qperq
) {
1230 std::unique_ptr
<SyncRes
> sr
;
1236 const DNSName
target("cname.powerdns.com.");
1238 sr
->setAsyncCallback([target
,&queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1242 if (isRootServer(ip
)) {
1244 setLWResult(res
, 0, false, false, true);
1245 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1246 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1248 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1250 setLWResult(res
, 0, true, false, false);
1251 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(queries
) + "-cname.powerdns.com");
1258 /* Set the maximum number of questions very low */
1259 SyncRes::s_maxqperq
= 5;
1262 vector
<DNSRecord
> ret
;
1263 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1266 catch(const ImmediateServFailException
& e
) {
1267 BOOST_CHECK_EQUAL(queries
, SyncRes::s_maxqperq
);
1271 BOOST_AUTO_TEST_CASE(test_throttled_server
) {
1272 std::unique_ptr
<SyncRes
> sr
;
1277 const DNSName
target("throttled.powerdns.com.");
1278 const ComboAddress
ns("192.0.2.1:53");
1279 size_t queriesToNS
= 0;
1281 sr
->setAsyncCallback([target
,ns
,&queriesToNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1283 if (isRootServer(ip
)) {
1285 setLWResult(res
, 0, false, false, true);
1286 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1287 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1289 } else if (ip
== ns
) {
1293 setLWResult(res
, 0, true, false, false);
1294 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1302 /* mark ns as down */
1303 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, 10000);
1305 vector
<DNSRecord
> ret
;
1306 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1307 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1308 BOOST_CHECK_EQUAL(ret
.size(), 0);
1309 /* we should not have sent any queries to ns */
1310 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1313 BOOST_AUTO_TEST_CASE(test_throttled_server_count
) {
1314 std::unique_ptr
<SyncRes
> sr
;
1319 const ComboAddress
ns("192.0.2.1:53");
1321 const size_t blocks
= 10;
1322 /* mark ns as down for 'blocks' queries */
1323 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, blocks
);
1325 for (size_t idx
= 0; idx
< blocks
; idx
++) {
1326 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1329 /* we have been throttled 'blocks' times, we should not be throttled anymore */
1330 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1333 BOOST_AUTO_TEST_CASE(test_throttled_server_time
) {
1334 std::unique_ptr
<SyncRes
> sr
;
1339 const ComboAddress
ns("192.0.2.1:53");
1341 const size_t seconds
= 1;
1342 /* mark ns as down for 'seconds' seconds */
1343 SyncRes::doThrottle(time(nullptr), ns
, seconds
, 10000);
1345 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1349 /* we should not be throttled anymore */
1350 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1353 BOOST_AUTO_TEST_CASE(test_dont_query_server
) {
1354 std::unique_ptr
<SyncRes
> sr
;
1359 const DNSName
target("throttled.powerdns.com.");
1360 const ComboAddress
ns("192.0.2.1:53");
1361 size_t queriesToNS
= 0;
1363 sr
->setAsyncCallback([target
,ns
,&queriesToNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1365 if (isRootServer(ip
)) {
1367 setLWResult(res
, 0, false, false, true);
1368 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1369 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1371 } else if (ip
== ns
) {
1375 setLWResult(res
, 0, true, false, false);
1376 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1384 /* prevent querying this NS */
1385 SyncRes::addDontQuery(Netmask(ns
));
1387 vector
<DNSRecord
> ret
;
1388 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1389 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1390 BOOST_CHECK_EQUAL(ret
.size(), 0);
1391 /* we should not have sent any queries to ns */
1392 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1395 BOOST_AUTO_TEST_CASE(test_root_nx_trust
) {
1396 std::unique_ptr
<SyncRes
> sr
;
1401 const DNSName
target1("powerdns.com.");
1402 const DNSName
target2("notpowerdns.com.");
1403 const ComboAddress
ns("192.0.2.1:53");
1404 size_t queriesCount
= 0;
1406 sr
->setAsyncCallback([target1
, target2
, ns
, &queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1410 if (isRootServer(ip
)) {
1412 if (domain
== target1
) {
1413 setLWResult(res
, RCode::NXDomain
, true, false, true);
1414 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1417 setLWResult(res
, 0, true, false, true);
1418 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1419 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1423 } else if (ip
== ns
) {
1425 setLWResult(res
, 0, true, false, false);
1426 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1434 vector
<DNSRecord
> ret
;
1435 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1436 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1437 BOOST_CHECK_EQUAL(ret
.size(), 1);
1438 /* one for target1 and one for the entire TLD */
1439 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1442 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1443 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1444 BOOST_CHECK_EQUAL(ret
.size(), 1);
1445 /* one for target1 and one for the entire TLD */
1446 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1448 /* we should have sent only one query */
1449 BOOST_CHECK_EQUAL(queriesCount
, 1);
1452 BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific
) {
1453 std::unique_ptr
<SyncRes
> sr
;
1455 initSR(sr
, true, false);
1459 const DNSName
target1("powerdns.com.");
1460 const DNSName
target2("notpowerdns.com.");
1461 const ComboAddress
ns("192.0.2.1:53");
1462 size_t queriesCount
= 0;
1464 /* This time the root denies target1 with a "com." SOA instead of a "." one.
1465 We should add target1 to the negcache, but not "com.". */
1467 sr
->setAsyncCallback([target1
, target2
, ns
, &queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1471 if (isRootServer(ip
)) {
1473 if (domain
== target1
) {
1474 setLWResult(res
, RCode::NXDomain
, true, false, true);
1475 addRecordToLW(res
, "com.", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1478 setLWResult(res
, 0, true, false, true);
1479 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1480 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1484 } else if (ip
== ns
) {
1486 setLWResult(res
, 0, true, false, false);
1487 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1495 vector
<DNSRecord
> ret
;
1496 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1497 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1498 BOOST_CHECK_EQUAL(ret
.size(), 1);
1500 /* even with root-nx-trust on and a NX answer from the root,
1501 we should not have cached the entire TLD this time. */
1502 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1505 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1506 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1507 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1508 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1509 BOOST_CHECK_EQUAL(ret
[0].d_name
, target2
);
1510 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress("192.0.2.2"));
1512 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1514 BOOST_CHECK_EQUAL(queriesCount
, 3);
1517 BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust
) {
1518 std::unique_ptr
<SyncRes
> sr
;
1523 const DNSName
target1("powerdns.com.");
1524 const DNSName
target2("notpowerdns.com.");
1525 const ComboAddress
ns("192.0.2.1:53");
1526 size_t queriesCount
= 0;
1528 sr
->setAsyncCallback([target1
, target2
, ns
, &queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1532 if (isRootServer(ip
)) {
1534 if (domain
== target1
) {
1535 setLWResult(res
, RCode::NXDomain
, true, false, true);
1536 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1539 setLWResult(res
, 0, true, false, true);
1540 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1541 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1545 } else if (ip
== ns
) {
1547 setLWResult(res
, 0, true, false, false);
1548 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1556 SyncRes::s_rootNXTrust
= false;
1558 vector
<DNSRecord
> ret
;
1559 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1560 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1561 BOOST_CHECK_EQUAL(ret
.size(), 1);
1562 /* one for target1 */
1563 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1566 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1567 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1568 BOOST_CHECK_EQUAL(ret
.size(), 1);
1569 /* one for target1 */
1570 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1572 /* we should have sent three queries */
1573 BOOST_CHECK_EQUAL(queriesCount
, 3);
1576 BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response
) {
1577 std::unique_ptr
<SyncRes
> sr
;
1582 const DNSName
target("www.powerdns.com.");
1583 const DNSName
cnameTarget("cname.powerdns.com.");
1585 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
1587 EDNSSubnetOpts incomingECS
;
1588 incomingECS
.source
= Netmask("192.0.2.128/32");
1589 sr
->setIncomingECSFound(true);
1590 sr
->setIncomingECS(incomingECS
);
1592 sr
->setAsyncCallback([target
,cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1594 BOOST_REQUIRE(srcmask
);
1595 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1597 if (isRootServer(ip
)) {
1598 setLWResult(res
, 0, false, false, true);
1599 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1600 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1603 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1604 if (domain
== target
) {
1605 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
1606 setLWResult(res
, RCode::NXDomain
, true, false, true);
1607 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1608 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1610 else if (domain
== cnameTarget
) {
1611 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
1612 but we might if we still chase the CNAME. */
1613 setLWResult(res
, RCode::NXDomain
, true, false, true);
1614 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1623 vector
<DNSRecord
> ret
;
1624 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1625 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1626 BOOST_CHECK_EQUAL(ret
.size(), 2);
1627 /* no negative cache entry because the response was variable */
1628 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0);
1631 BOOST_AUTO_TEST_CASE(test_ns_speed
) {
1632 std::unique_ptr
<SyncRes
> sr
;
1637 const DNSName
target("powerdns.com.");
1639 std::map
<ComboAddress
, uint64_t> nsCounts
;
1641 sr
->setAsyncCallback([target
,&nsCounts
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1643 if (isRootServer(ip
)) {
1644 setLWResult(res
, 0, false, false, true);
1645 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1646 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1647 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1649 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1650 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1651 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1652 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 3600);
1653 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 3600);
1654 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 3600);
1660 if (ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("192.0.2.2:53")) {
1661 BOOST_CHECK_LT(nsCounts
.size(), 3);
1663 /* let's time out on pdns-public-ns2.powerdns.com. */
1666 else if (ip
== ComboAddress("192.0.2.1:53")) {
1667 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1669 setLWResult(res
, 0, true, false, true);
1670 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1681 gettimeofday(&now
, 0);
1683 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1684 then pdns-public-ns1.powerdns.com. on IPv4 */
1685 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now
);
1686 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now
);
1687 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now
);
1688 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now
);
1689 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now
);
1690 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now
);
1692 vector
<DNSRecord
> ret
;
1693 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1694 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1695 BOOST_CHECK_EQUAL(ret
.size(), 1);
1696 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1697 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.1:53")], 1);
1698 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.2:53")], 1);
1699 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("[2001:DB8::2]:53")], 1);
1702 BOOST_AUTO_TEST_CASE(test_flawed_nsset
) {
1703 std::unique_ptr
<SyncRes
> sr
;
1708 const DNSName
target("powerdns.com.");
1710 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1712 if (isRootServer(ip
)) {
1713 setLWResult(res
, 0, false, false, true);
1714 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1716 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1719 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1720 setLWResult(res
, 0, true, false, true);
1721 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1728 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1729 time_t now
= time(nullptr);
1730 std::vector
<DNSRecord
> records
;
1731 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1732 addRecordToList(records
, target
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, now
+ 3600);
1734 t_RC
->replace(now
, target
, QType(QType::NS
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1736 vector
<DNSRecord
> ret
;
1737 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1738 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1739 BOOST_CHECK_EQUAL(ret
.size(), 1);
1742 BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset
) {
1743 std::unique_ptr
<SyncRes
> sr
;
1748 const DNSName
target("powerdns.com.");
1749 size_t queriesCount
= 0;
1751 sr
->setAsyncCallback([&queriesCount
,target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1755 if (isRootServer(ip
) && domain
== target
) {
1756 setLWResult(res
, 0, false, false, true);
1757 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1758 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1760 } else if (domain
== DNSName("pdns-public-ns2.powerdns.com.") || domain
== DNSName("pdns-public-ns3.powerdns.com.")){
1761 setLWResult(res
, 0, true, false, true);
1762 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1769 vector
<DNSRecord
> ret
;
1770 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1771 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1772 BOOST_CHECK_EQUAL(ret
.size(), 0);
1773 /* one query to get NSs, then A and AAAA for each NS */
1774 BOOST_CHECK_EQUAL(queriesCount
, 5);
1777 BOOST_AUTO_TEST_CASE(test_cache_hit
) {
1778 std::unique_ptr
<SyncRes
> sr
;
1783 const DNSName
target("powerdns.com.");
1785 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1790 /* we populate the cache with eveything we need */
1791 time_t now
= time(nullptr);
1792 std::vector
<DNSRecord
> records
;
1793 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1795 addRecordToList(records
, target
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, now
+ 3600);
1796 t_RC
->replace(now
, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1798 vector
<DNSRecord
> ret
;
1799 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1800 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1801 BOOST_CHECK_EQUAL(ret
.size(), 1);
1804 BOOST_AUTO_TEST_CASE(test_no_rd
) {
1805 std::unique_ptr
<SyncRes
> sr
;
1810 const DNSName
target("powerdns.com.");
1811 size_t queriesCount
= 0;
1815 sr
->setAsyncCallback([target
,&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1821 vector
<DNSRecord
> ret
;
1822 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1823 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1824 BOOST_CHECK_EQUAL(ret
.size(), 0);
1825 BOOST_CHECK_EQUAL(queriesCount
, 0);
1828 BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl
) {
1829 std::unique_ptr
<SyncRes
> sr
;
1830 const time_t now
= time(nullptr);
1835 const DNSName
target("cachettl.powerdns.com.");
1836 const ComboAddress
ns("192.0.2.1:53");
1838 sr
->setAsyncCallback([target
,ns
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1840 if (isRootServer(ip
)) {
1842 setLWResult(res
, 0, false, false, true);
1843 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1844 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 7200);
1846 } else if (ip
== ns
) {
1848 setLWResult(res
, 0, true, false, false);
1849 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
1857 SyncRes::s_minimumTTL
= 60;
1858 SyncRes::s_maxcachettl
= 3600;
1860 vector
<DNSRecord
> ret
;
1861 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1862 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1863 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1864 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumTTL
);
1866 const ComboAddress who
;
1867 vector
<DNSRecord
> cached
;
1868 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1869 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
1870 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1871 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
1874 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
1875 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
1876 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1877 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
1880 BOOST_AUTO_TEST_CASE(test_cache_expired_ttl
) {
1881 std::unique_ptr
<SyncRes
> sr
;
1886 const DNSName
target("powerdns.com.");
1888 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1890 if (isRootServer(ip
)) {
1891 setLWResult(res
, 0, false, false, true);
1892 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1894 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1897 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1898 setLWResult(res
, 0, true, false, true);
1899 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1906 /* we populate the cache with entries that expired 60s ago*/
1907 time_t now
= time(nullptr);
1908 std::vector
<DNSRecord
> records
;
1909 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1910 addRecordToList(records
, target
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, now
- 60);
1912 t_RC
->replace(now
- 3600, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1914 vector
<DNSRecord
> ret
;
1915 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1916 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1917 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1918 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1919 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
1922 BOOST_AUTO_TEST_CASE(test_delegation_only
) {
1923 std::unique_ptr
<SyncRes
> sr
;
1928 /* Thanks, Verisign */
1929 SyncRes::addDelegationOnly(DNSName("com."));
1930 SyncRes::addDelegationOnly(DNSName("net."));
1932 const DNSName
target("nx-powerdns.com.");
1934 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1936 if (isRootServer(ip
)) {
1937 setLWResult(res
, 0, false, false, true);
1938 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1939 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1941 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1943 setLWResult(res
, 0, true, false, true);
1944 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
1951 vector
<DNSRecord
> ret
;
1952 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1953 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1954 BOOST_CHECK_EQUAL(ret
.size(), 0);
1957 BOOST_AUTO_TEST_CASE(test_unauth_any
) {
1958 std::unique_ptr
<SyncRes
> sr
;
1963 const DNSName
target("powerdns.com.");
1965 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1967 if (isRootServer(ip
)) {
1968 setLWResult(res
, 0, false, false, true);
1969 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1970 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1972 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1974 setLWResult(res
, 0, false, false, true);
1975 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
1982 vector
<DNSRecord
> ret
;
1983 int res
= sr
->beginResolve(target
, QType(QType::ANY
), QClass::IN
, ret
);
1984 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1985 BOOST_CHECK_EQUAL(ret
.size(), 0);
1988 BOOST_AUTO_TEST_CASE(test_no_data
) {
1989 std::unique_ptr
<SyncRes
> sr
;
1994 const DNSName
target("powerdns.com.");
1996 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
1998 setLWResult(res
, 0, true, false, true);
2002 vector
<DNSRecord
> ret
;
2003 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2004 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2005 BOOST_CHECK_EQUAL(ret
.size(), 0);
2008 BOOST_AUTO_TEST_CASE(test_skip_opt_any
) {
2009 std::unique_ptr
<SyncRes
> sr
;
2014 const DNSName
target("powerdns.com.");
2016 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2018 setLWResult(res
, 0, true, false, true);
2019 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2020 addRecordToLW(res
, domain
, QType::ANY
, "0 0");
2021 addRecordToLW(res
, domain
, QType::OPT
, "");
2025 vector
<DNSRecord
> ret
;
2026 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2027 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2028 BOOST_CHECK_EQUAL(ret
.size(), 1);
2031 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec
) {
2032 std::unique_ptr
<SyncRes
> sr
;
2037 const DNSName
target("powerdns.com.");
2039 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2041 setLWResult(res
, 0, true, false, true);
2042 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2043 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2044 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2045 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2046 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2050 vector
<DNSRecord
> ret
;
2051 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2052 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2053 BOOST_CHECK_EQUAL(ret
.size(), 1);
2056 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec
) {
2057 std::unique_ptr
<SyncRes
> sr
;
2062 const DNSName
target("powerdns.com.");
2064 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2066 setLWResult(res
, 0, true, false, true);
2067 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2068 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2069 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2070 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2071 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2075 vector
<DNSRecord
> ret
;
2076 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2077 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2078 BOOST_CHECK_EQUAL(ret
.size(), 4);
2081 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec
) {
2082 std::unique_ptr
<SyncRes
> sr
;
2087 const DNSName
target("powerdns.com.");
2089 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2091 setLWResult(res
, RCode::NXDomain
, true, false, true);
2092 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2093 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2094 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2095 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2096 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2100 vector
<DNSRecord
> ret
;
2101 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2102 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2103 BOOST_CHECK_EQUAL(ret
.size(), 1);
2106 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec
) {
2107 std::unique_ptr
<SyncRes
> sr
;
2112 const DNSName
target("powerdns.com.");
2114 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2116 setLWResult(res
, RCode::NXDomain
, true, false, true);
2117 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2118 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2119 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2120 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2121 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2125 vector
<DNSRecord
> ret
;
2126 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2127 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2128 BOOST_CHECK_EQUAL(ret
.size(), 4);
2131 BOOST_AUTO_TEST_CASE(test_qclass_none
) {
2132 std::unique_ptr
<SyncRes
> sr
;
2137 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
2138 size_t queriesCount
= 0;
2140 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2146 const DNSName
target("powerdns.com.");
2147 vector
<DNSRecord
> ret
;
2148 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::NONE
, ret
);
2149 BOOST_CHECK_EQUAL(res
, -1);
2150 BOOST_CHECK_EQUAL(ret
.size(), 0);
2151 BOOST_CHECK_EQUAL(queriesCount
, 0);
2154 BOOST_AUTO_TEST_CASE(test_xfr
) {
2155 std::unique_ptr
<SyncRes
> sr
;
2160 /* {A,I}XFR should be rejected right away */
2161 size_t queriesCount
= 0;
2163 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2165 cerr
<<"asyncresolve called to ask "<<ip
.toStringWithPort()<<" about "<<domain
.toString()<<" / "<<QType(type
).getName()<<" over "<<(doTCP
? "TCP" : "UDP")<<" (rd: "<<sendRDQuery
<<", EDNS0 level: "<<EDNS0Level
<<")"<<endl
;
2170 const DNSName
target("powerdns.com.");
2171 vector
<DNSRecord
> ret
;
2172 int res
= sr
->beginResolve(target
, QType(QType::AXFR
), QClass::IN
, ret
);
2173 BOOST_CHECK_EQUAL(res
, -1);
2174 BOOST_CHECK_EQUAL(ret
.size(), 0);
2175 BOOST_CHECK_EQUAL(queriesCount
, 0);
2177 res
= sr
->beginResolve(target
, QType(QType::IXFR
), QClass::IN
, ret
);
2178 BOOST_CHECK_EQUAL(res
, -1);
2179 BOOST_CHECK_EQUAL(ret
.size(), 0);
2180 BOOST_CHECK_EQUAL(queriesCount
, 0);
2183 BOOST_AUTO_TEST_CASE(test_special_names
) {
2184 std::unique_ptr
<SyncRes
> sr
;
2189 /* special names should be handled internally */
2191 size_t queriesCount
= 0;
2193 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2199 vector
<DNSRecord
> ret
;
2200 int res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
2201 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2202 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2203 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2204 BOOST_CHECK_EQUAL(queriesCount
, 0);
2207 res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
2208 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2209 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2210 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2211 BOOST_CHECK_EQUAL(queriesCount
, 0);
2214 res
= sr
->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
2215 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2216 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2217 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2218 BOOST_CHECK_EQUAL(queriesCount
, 0);
2221 res
= sr
->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
2222 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2223 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2224 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2225 BOOST_CHECK_EQUAL(queriesCount
, 0);
2228 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::A
), QClass::IN
, ret
);
2229 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2230 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2231 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2232 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), "127.0.0.1");
2233 BOOST_CHECK_EQUAL(queriesCount
, 0);
2236 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::AAAA
), QClass::IN
, ret
);
2237 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2238 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2239 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
2240 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(ret
[0])->getCA().toString(), "::1");
2241 BOOST_CHECK_EQUAL(queriesCount
, 0);
2244 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::ANY
), QClass::IN
, ret
);
2245 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2246 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2247 for (const auto& rec
: ret
) {
2248 BOOST_REQUIRE((rec
.d_type
== QType::A
) || rec
.d_type
== QType::AAAA
);
2249 if (rec
.d_type
== QType::A
) {
2250 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(rec
)->getCA().toString(), "127.0.0.1");
2253 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(rec
)->getCA().toString(), "::1");
2256 BOOST_CHECK_EQUAL(queriesCount
, 0);
2259 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2260 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2261 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2262 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2263 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2264 BOOST_CHECK_EQUAL(queriesCount
, 0);
2267 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2268 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2269 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2270 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2271 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2272 BOOST_CHECK_EQUAL(queriesCount
, 0);
2275 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2276 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2277 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2278 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2279 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2280 BOOST_CHECK_EQUAL(queriesCount
, 0);
2283 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2284 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2285 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2286 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2287 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2288 BOOST_CHECK_EQUAL(queriesCount
, 0);
2291 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2292 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2293 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2294 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2295 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2296 BOOST_CHECK_EQUAL(queriesCount
, 0);
2299 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2300 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2301 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2302 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2303 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2304 BOOST_CHECK_EQUAL(queriesCount
, 0);
2307 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz
) {
2308 std::unique_ptr
<SyncRes
> sr
;
2313 const DNSName
target("rpz.powerdns.com.");
2314 const ComboAddress
ns("192.0.2.1:53");
2316 sr
->setAsyncCallback([target
,ns
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2318 if (isRootServer(ip
)) {
2319 setLWResult(res
, false, true, false, true);
2320 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2321 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2323 } else if (ip
== ns
) {
2325 setLWResult(res
, 0, true, false, true);
2326 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2333 DNSFilterEngine::Policy pol
;
2334 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2335 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2336 zone
->setName("Unit test policy 0");
2337 zone
->addNSIPTrigger(Netmask(ns
, 32), pol
);
2338 auto luaconfsCopy
= g_luaconfs
.getCopy();
2339 luaconfsCopy
.dfe
.addZone(zone
);
2340 g_luaconfs
.setState(luaconfsCopy
);
2342 vector
<DNSRecord
> ret
;
2343 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2344 BOOST_CHECK_EQUAL(res
, -2);
2345 BOOST_CHECK_EQUAL(ret
.size(), 0);
2348 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz
) {
2349 std::unique_ptr
<SyncRes
> sr
;
2354 const DNSName
target("rpz.powerdns.com.");
2355 const ComboAddress
ns("[2001:DB8::42]:53");
2357 sr
->setAsyncCallback([target
,ns
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2359 if (isRootServer(ip
)) {
2360 setLWResult(res
, 0, false, false, true);
2361 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2362 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2364 } else if (ip
== ns
) {
2366 setLWResult(res
, 0, true, false, true);
2367 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2374 DNSFilterEngine::Policy pol
;
2375 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2376 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2377 zone
->setName("Unit test policy 0");
2378 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2379 auto luaconfsCopy
= g_luaconfs
.getCopy();
2380 luaconfsCopy
.dfe
.addZone(zone
);
2381 g_luaconfs
.setState(luaconfsCopy
);
2383 vector
<DNSRecord
> ret
;
2384 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2385 BOOST_CHECK_EQUAL(res
, -2);
2386 BOOST_CHECK_EQUAL(ret
.size(), 0);
2389 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz
) {
2390 std::unique_ptr
<SyncRes
> sr
;
2395 const DNSName
target("rpz.powerdns.com.");
2396 const ComboAddress
ns("192.0.2.1:53");
2397 const DNSName
nsName("ns1.powerdns.com.");
2399 sr
->setAsyncCallback([target
,ns
,nsName
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2401 if (isRootServer(ip
)) {
2402 setLWResult(res
, 0, false, false, true);
2403 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2404 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2406 } else if (ip
== ns
) {
2408 setLWResult(res
, 0, true, false, true);
2409 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2416 DNSFilterEngine::Policy pol
;
2417 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2418 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2419 zone
->setName("Unit test policy 0");
2420 zone
->addNSTrigger(nsName
, pol
);
2421 auto luaconfsCopy
= g_luaconfs
.getCopy();
2422 luaconfsCopy
.dfe
.addZone(zone
);
2423 g_luaconfs
.setState(luaconfsCopy
);
2425 vector
<DNSRecord
> ret
;
2426 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2427 BOOST_CHECK_EQUAL(res
, -2);
2428 BOOST_CHECK_EQUAL(ret
.size(), 0);
2431 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled
) {
2432 std::unique_ptr
<SyncRes
> sr
;
2437 const DNSName
target("rpz.powerdns.com.");
2438 const ComboAddress
ns("192.0.2.1:53");
2439 const DNSName
nsName("ns1.powerdns.com.");
2441 sr
->setAsyncCallback([target
,ns
,nsName
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2443 if (isRootServer(ip
)) {
2444 setLWResult(res
, 0, false, false, true);
2445 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2446 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2448 } else if (ip
== ns
) {
2450 setLWResult(res
, 0, true, false, true);
2451 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2458 DNSFilterEngine::Policy pol
;
2459 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2460 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2461 zone
->setName("Unit test policy 0");
2462 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2463 zone
->addNSTrigger(nsName
, pol
);
2464 auto luaconfsCopy
= g_luaconfs
.getCopy();
2465 luaconfsCopy
.dfe
.addZone(zone
);
2466 g_luaconfs
.setState(luaconfsCopy
);
2468 /* RPZ is disabled for this query, we should not be blocked */
2469 sr
->setWantsRPZ(false);
2471 vector
<DNSRecord
> ret
;
2472 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2473 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2474 BOOST_CHECK_EQUAL(ret
.size(), 1);
2477 BOOST_AUTO_TEST_CASE(test_forward_zone_nord
) {
2478 std::unique_ptr
<SyncRes
> sr
;
2483 const DNSName
target("powerdns.com.");
2484 const ComboAddress
ns("192.0.2.1:53");
2485 const ComboAddress
forwardedNS("192.0.2.42:53");
2487 SyncRes::AuthDomain ad
;
2488 ad
.d_rdForward
= false;
2489 ad
.d_servers
.push_back(forwardedNS
);
2490 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2492 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2494 if (ip
== forwardedNS
) {
2495 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2497 setLWResult(res
, 0, true, false, true);
2498 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2505 /* simulate a no-RD query */
2508 vector
<DNSRecord
> ret
;
2509 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2510 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2511 BOOST_CHECK_EQUAL(ret
.size(), 1);
2514 BOOST_AUTO_TEST_CASE(test_forward_zone_rd
) {
2515 std::unique_ptr
<SyncRes
> sr
;
2520 const DNSName
target("powerdns.com.");
2521 const ComboAddress
ns("192.0.2.1:53");
2522 const ComboAddress
forwardedNS("192.0.2.42:53");
2524 SyncRes::AuthDomain ad
;
2525 ad
.d_rdForward
= false;
2526 ad
.d_servers
.push_back(forwardedNS
);
2527 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2529 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2531 if (ip
== forwardedNS
) {
2532 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2534 setLWResult(res
, 0, true, false, true);
2535 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2542 vector
<DNSRecord
> ret
;
2543 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2544 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2545 BOOST_CHECK_EQUAL(ret
.size(), 1);
2548 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord
) {
2549 std::unique_ptr
<SyncRes
> sr
;
2554 const DNSName
target("powerdns.com.");
2555 const ComboAddress
ns("192.0.2.1:53");
2556 const ComboAddress
forwardedNS("192.0.2.42:53");
2558 SyncRes::AuthDomain ad
;
2559 ad
.d_rdForward
= true;
2560 ad
.d_servers
.push_back(forwardedNS
);
2561 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2563 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2565 if (ip
== forwardedNS
) {
2566 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2568 setLWResult(res
, 0, true, false, true);
2569 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2576 /* simulate a no-RD query */
2579 vector
<DNSRecord
> ret
;
2580 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2581 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2582 BOOST_CHECK_EQUAL(ret
.size(), 1);
2585 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd
) {
2586 std::unique_ptr
<SyncRes
> sr
;
2591 const DNSName
target("powerdns.com.");
2592 const ComboAddress
ns("192.0.2.1:53");
2593 const ComboAddress
forwardedNS("192.0.2.42:53");
2595 SyncRes::AuthDomain ad
;
2596 ad
.d_rdForward
= true;
2597 ad
.d_servers
.push_back(forwardedNS
);
2598 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2600 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2602 if (ip
== forwardedNS
) {
2603 BOOST_CHECK_EQUAL(sendRDQuery
, true);
2605 setLWResult(res
, 0, true, false, true);
2606 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2613 vector
<DNSRecord
> ret
;
2614 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2615 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2616 BOOST_CHECK_EQUAL(ret
.size(), 1);
2619 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_oob
) {
2620 std::unique_ptr
<SyncRes
> sr
;
2622 initSR(sr
, true, false);
2626 size_t queriesCount
= 0;
2627 const DNSName
target("test.xx.");
2628 const ComboAddress
targetAddr("127.0.0.1");
2629 const DNSName
ns("localhost.");
2630 const ComboAddress
nsAddr("127.0.0.1");
2631 const DNSName
authZone("test.xx");
2633 SyncRes::AuthDomain ad
;
2635 dr
.d_place
= DNSResourceRecord::ANSWER
;
2636 dr
.d_name
= authZone
;
2637 dr
.d_type
= QType::NS
;
2639 dr
.d_content
= std::make_shared
<NSRecordContent
>("localhost.");
2640 ad
.d_records
.insert(dr
);
2642 dr
.d_place
= DNSResourceRecord::ANSWER
;
2643 dr
.d_name
= authZone
;
2644 dr
.d_type
= QType::A
;
2646 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
2647 ad
.d_records
.insert(dr
);
2649 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
2651 sr
->setAsyncCallback([&queriesCount
,nsAddr
,target
,targetAddr
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2656 vector
<DNSRecord
> ret
;
2657 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2658 BOOST_CHECK_EQUAL(res
, 0);
2659 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2660 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2661 BOOST_CHECK_EQUAL(queriesCount
, 0);
2662 BOOST_CHECK(sr
->wasOutOfBand());
2664 /* a second time, to check that the OOB flag is set when the query cache is used */
2666 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2667 BOOST_CHECK_EQUAL(res
, 0);
2668 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2669 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2670 BOOST_CHECK_EQUAL(queriesCount
, 0);
2671 BOOST_CHECK(sr
->wasOutOfBand());
2674 BOOST_AUTO_TEST_CASE(test_auth_zone
) {
2675 std::unique_ptr
<SyncRes
> sr
;
2680 size_t queriesCount
= 0;
2681 const DNSName
target("powerdns.com.");
2682 const ComboAddress
addr("192.0.2.5");
2684 SyncRes::AuthDomain ad
;
2687 dr
.d_place
= DNSResourceRecord::ANSWER
;
2689 dr
.d_type
= QType::SOA
;
2691 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2692 ad
.d_records
.insert(dr
);
2694 dr
.d_place
= DNSResourceRecord::ANSWER
;
2696 dr
.d_type
= QType::A
;
2698 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
2699 ad
.d_records
.insert(dr
);
2701 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2702 (*map
)[target
] = ad
;
2703 SyncRes::setDomainMap(map
);
2705 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2708 setLWResult(res
, 0, true, false, true);
2709 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2713 vector
<DNSRecord
> ret
;
2714 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2715 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2716 BOOST_CHECK_EQUAL(ret
.size(), 1);
2717 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2718 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
2719 BOOST_CHECK_EQUAL(queriesCount
, 0);
2722 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob
) {
2723 std::unique_ptr
<SyncRes
> sr
;
2728 size_t queriesCount
= 0;
2729 const DNSName
target("powerdns.com.");
2730 const DNSName
authZone("internal.powerdns.com.");
2731 const ComboAddress
addr("192.0.2.5");
2733 SyncRes::AuthDomain ad
;
2734 ad
.d_name
= authZone
;
2736 dr
.d_place
= DNSResourceRecord::ANSWER
;
2737 dr
.d_name
= authZone
;
2738 dr
.d_type
= QType::SOA
;
2740 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2741 ad
.d_records
.insert(dr
);
2743 dr
.d_place
= DNSResourceRecord::ANSWER
;
2744 dr
.d_name
= authZone
;
2745 dr
.d_type
= QType::A
;
2747 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
2748 ad
.d_records
.insert(dr
);
2750 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2751 (*map
)[authZone
] = ad
;
2752 SyncRes::setDomainMap(map
);
2754 sr
->setAsyncCallback([&queriesCount
,target
,authZone
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2758 if (domain
== target
) {
2759 setLWResult(res
, 0, true, false, true);
2760 addRecordToLW(res
, target
, QType::CNAME
, authZone
.toString(), DNSResourceRecord::ANSWER
, 3600);
2767 vector
<DNSRecord
> ret
;
2768 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2769 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2770 BOOST_CHECK_EQUAL(ret
.size(), 2);
2771 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2772 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), authZone
.toString());
2773 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2774 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
2775 BOOST_CHECK_EQUAL(queriesCount
, 1);
2778 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb
) {
2779 std::unique_ptr
<SyncRes
> sr
;
2784 size_t queriesCount
= 0;
2785 const DNSName
target("powerdns.com.");
2786 const DNSName
externalCNAME("www.open-xchange.com.");
2787 const ComboAddress
addr("192.0.2.5");
2789 SyncRes::AuthDomain ad
;
2792 dr
.d_place
= DNSResourceRecord::ANSWER
;
2794 dr
.d_type
= QType::SOA
;
2796 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2797 ad
.d_records
.insert(dr
);
2799 dr
.d_place
= DNSResourceRecord::ANSWER
;
2801 dr
.d_type
= QType::CNAME
;
2803 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(externalCNAME
);
2804 ad
.d_records
.insert(dr
);
2806 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2807 (*map
)[target
] = ad
;
2808 SyncRes::setDomainMap(map
);
2810 sr
->setAsyncCallback([&queriesCount
,externalCNAME
,addr
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2814 if (domain
== externalCNAME
) {
2815 setLWResult(res
, 0, true, false, true);
2816 addRecordToLW(res
, externalCNAME
, QType::A
, addr
.toString(), DNSResourceRecord::ANSWER
, 3600);
2823 vector
<DNSRecord
> ret
;
2824 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2825 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2826 BOOST_CHECK_EQUAL(ret
.size(), 2);
2827 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2828 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), externalCNAME
.toString());
2829 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2830 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
2831 BOOST_CHECK_EQUAL(queriesCount
, 1);
2834 BOOST_AUTO_TEST_CASE(test_auth_zone_nodata
) {
2835 std::unique_ptr
<SyncRes
> sr
;
2840 size_t queriesCount
= 0;
2841 const DNSName
target("nodata.powerdns.com.");
2842 const DNSName
authZone("powerdns.com");
2844 SyncRes::AuthDomain ad
;
2845 ad
.d_name
= authZone
;
2847 dr
.d_place
= DNSResourceRecord::ANSWER
;
2849 dr
.d_type
= QType::A
;
2851 dr
.d_content
= std::make_shared
<ARecordContent
>(ComboAddress("192.0.2.1"));
2852 ad
.d_records
.insert(dr
);
2854 dr
.d_place
= DNSResourceRecord::ANSWER
;
2855 dr
.d_name
= authZone
;
2856 dr
.d_type
= QType::SOA
;
2858 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2859 ad
.d_records
.insert(dr
);
2861 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2862 (*map
)[authZone
] = ad
;
2863 SyncRes::setDomainMap(map
);
2865 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2872 vector
<DNSRecord
> ret
;
2873 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
2874 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2875 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2876 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
2877 BOOST_CHECK_EQUAL(queriesCount
, 0);
2880 BOOST_AUTO_TEST_CASE(test_auth_zone_nx
) {
2881 std::unique_ptr
<SyncRes
> sr
;
2886 size_t queriesCount
= 0;
2887 const DNSName
target("nx.powerdns.com.");
2888 const DNSName
authZone("powerdns.com");
2890 SyncRes::AuthDomain ad
;
2891 ad
.d_name
= authZone
;
2893 dr
.d_place
= DNSResourceRecord::ANSWER
;
2894 dr
.d_name
= DNSName("powerdns.com.");
2895 dr
.d_type
= QType::SOA
;
2897 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2898 ad
.d_records
.insert(dr
);
2900 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2901 (*map
)[authZone
] = ad
;
2902 SyncRes::setDomainMap(map
);
2904 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2911 vector
<DNSRecord
> ret
;
2912 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2913 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2914 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2915 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
2916 BOOST_CHECK_EQUAL(queriesCount
, 0);
2919 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation
) {
2920 std::unique_ptr
<SyncRes
> sr
;
2925 size_t queriesCount
= 0;
2926 const DNSName
target("www.test.powerdns.com.");
2927 const ComboAddress
targetAddr("192.0.2.2");
2928 const DNSName
ns("ns1.test.powerdns.com.");
2929 const ComboAddress
nsAddr("192.0.2.1");
2930 const DNSName
authZone("powerdns.com");
2932 SyncRes::AuthDomain ad
;
2933 ad
.d_name
= authZone
;
2935 dr
.d_place
= DNSResourceRecord::ANSWER
;
2936 dr
.d_name
= authZone
;
2937 dr
.d_type
= QType::SOA
;
2939 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2940 ad
.d_records
.insert(dr
);
2942 dr
.d_place
= DNSResourceRecord::ANSWER
;
2943 dr
.d_name
= DNSName("test.powerdns.com.");
2944 dr
.d_type
= QType::NS
;
2946 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
2947 ad
.d_records
.insert(dr
);
2949 dr
.d_place
= DNSResourceRecord::ANSWER
;
2951 dr
.d_type
= QType::A
;
2953 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
2954 ad
.d_records
.insert(dr
);
2956 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2957 (*map
)[authZone
] = ad
;
2958 SyncRes::setDomainMap(map
);
2960 sr
->setAsyncCallback([&queriesCount
,target
,targetAddr
,nsAddr
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
2963 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
2964 setLWResult(res
, 0, true, false, true);
2965 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
2972 vector
<DNSRecord
> ret
;
2973 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2974 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2975 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2976 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2977 BOOST_CHECK_EQUAL(queriesCount
, 1);
2980 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point
) {
2981 std::unique_ptr
<SyncRes
> sr
;
2986 size_t queriesCount
= 0;
2987 const DNSName
target("test.powerdns.com.");
2988 const ComboAddress
targetAddr("192.0.2.2");
2989 const DNSName
ns("ns1.test.powerdns.com.");
2990 const ComboAddress
nsAddr("192.0.2.1");
2991 const DNSName
authZone("powerdns.com");
2993 SyncRes::AuthDomain ad
;
2994 ad
.d_name
= authZone
;
2996 dr
.d_place
= DNSResourceRecord::ANSWER
;
2997 dr
.d_name
= authZone
;
2998 dr
.d_type
= QType::SOA
;
3000 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3001 ad
.d_records
.insert(dr
);
3003 dr
.d_place
= DNSResourceRecord::ANSWER
;
3004 dr
.d_name
= DNSName("test.powerdns.com.");
3005 dr
.d_type
= QType::NS
;
3007 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3008 ad
.d_records
.insert(dr
);
3010 dr
.d_place
= DNSResourceRecord::ANSWER
;
3012 dr
.d_type
= QType::A
;
3014 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3015 ad
.d_records
.insert(dr
);
3017 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3018 (*map
)[authZone
] = ad
;
3019 SyncRes::setDomainMap(map
);
3021 sr
->setAsyncCallback([&queriesCount
,nsAddr
,target
,targetAddr
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3025 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3026 setLWResult(res
, 0, true, false, true);
3027 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3034 vector
<DNSRecord
> ret
;
3035 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3036 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3037 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3038 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3039 BOOST_CHECK_EQUAL(queriesCount
, 1);
3042 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard
) {
3043 std::unique_ptr
<SyncRes
> sr
;
3048 size_t queriesCount
= 0;
3049 const DNSName
target("test.powerdns.com.");
3050 const ComboAddress
targetAddr("192.0.2.2");
3051 const DNSName
authZone("powerdns.com");
3053 SyncRes::AuthDomain ad
;
3054 ad
.d_name
= authZone
;
3056 dr
.d_place
= DNSResourceRecord::ANSWER
;
3057 dr
.d_name
= authZone
;
3058 dr
.d_type
= QType::SOA
;
3060 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3061 ad
.d_records
.insert(dr
);
3063 dr
.d_place
= DNSResourceRecord::ANSWER
;
3064 dr
.d_name
= DNSName("*.powerdns.com.");
3065 dr
.d_type
= QType::A
;
3067 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3068 ad
.d_records
.insert(dr
);
3070 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3071 (*map
)[authZone
] = ad
;
3072 SyncRes::setDomainMap(map
);
3074 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3081 vector
<DNSRecord
> ret
;
3082 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3083 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3084 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3085 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3086 BOOST_CHECK_EQUAL(queriesCount
, 0);
3089 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata
) {
3090 std::unique_ptr
<SyncRes
> sr
;
3095 size_t queriesCount
= 0;
3096 const DNSName
target("test.powerdns.com.");
3097 const ComboAddress
targetAddr("192.0.2.2");
3098 const DNSName
authZone("powerdns.com");
3100 SyncRes::AuthDomain ad
;
3101 ad
.d_name
= authZone
;
3103 dr
.d_place
= DNSResourceRecord::ANSWER
;
3104 dr
.d_name
= authZone
;
3105 dr
.d_type
= QType::SOA
;
3107 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3108 ad
.d_records
.insert(dr
);
3110 dr
.d_place
= DNSResourceRecord::ANSWER
;
3111 dr
.d_name
= DNSName("*.powerdns.com.");
3112 dr
.d_type
= QType::A
;
3114 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3115 ad
.d_records
.insert(dr
);
3117 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3118 (*map
)[authZone
] = ad
;
3119 SyncRes::setDomainMap(map
);
3121 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3128 vector
<DNSRecord
> ret
;
3129 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3130 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3131 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3132 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3133 BOOST_CHECK_EQUAL(queriesCount
, 0);
3136 BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only
) {
3137 std::unique_ptr
<SyncRes
> sr
;
3142 size_t queriesCount
= 0;
3143 const DNSName
target("powerdns.com.");
3144 const ComboAddress
addr("192.0.2.5");
3146 SyncRes::AuthDomain ad
;
3149 dr
.d_place
= DNSResourceRecord::ANSWER
;
3151 dr
.d_type
= QType::SOA
;
3153 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3154 ad
.d_records
.insert(dr
);
3156 dr
.d_place
= DNSResourceRecord::ANSWER
;
3158 dr
.d_type
= QType::A
;
3160 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3161 ad
.d_records
.insert(dr
);
3163 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3164 (*map
)[target
] = ad
;
3165 SyncRes::setDomainMap(map
);
3167 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3170 setLWResult(res
, 0, true, false, true);
3171 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
3175 /* simulate a no-RD query */
3178 vector
<DNSRecord
> ret
;
3179 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3180 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3181 BOOST_CHECK_EQUAL(ret
.size(), 1);
3182 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3183 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3184 BOOST_CHECK_EQUAL(queriesCount
, 0);
3187 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig
) {
3190 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3191 dcke
->create(dcke
->getBits());
3192 // cerr<<dcke->convertToISC()<<endl;
3193 DNSSECPrivateKey dpk
;
3197 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
3198 recordcontents
.push_back(getRecordContent(QType::A
, "192.0.2.1"));
3200 DNSName
qname("powerdns.com.");
3202 time_t now
= time(nullptr);
3203 RRSIGRecordContent rrc
;
3204 /* this RRSIG is valid for the current second only */
3205 computeRRSIG(dpk
, qname
, qname
, QType::A
, 600, 0, rrc
, recordcontents
, boost::none
, now
);
3208 keyset
.insert(std::make_shared
<DNSKEYRecordContent
>(dpk
.getDNSKEY()));
3210 std::vector
<std::shared_ptr
<RRSIGRecordContent
> > sigs
;
3211 sigs
.push_back(std::make_shared
<RRSIGRecordContent
>(rrc
));
3213 BOOST_CHECK(validateWithKeySet(now
, qname
, recordcontents
, sigs
, keyset
));
3216 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk
) {
3217 std::unique_ptr
<SyncRes
> sr
;
3220 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3223 const DNSName
target(".");
3226 auto luaconfsCopy
= g_luaconfs
.getCopy();
3227 luaconfsCopy
.dsAnchors
.clear();
3228 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3229 g_luaconfs
.setState(luaconfsCopy
);
3231 size_t queriesCount
= 0;
3233 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3236 if (domain
== target
&& type
== QType::NS
) {
3238 setLWResult(res
, 0, true, false, true);
3239 char addr
[] = "a.root-servers.net.";
3240 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3242 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3245 addRRSIG(keys
, res
->d_records
, domain
, 300);
3247 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3248 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3251 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3253 setLWResult(res
, 0, true, false, true);
3255 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3256 addRRSIG(keys
, res
->d_records
, domain
, 300);
3264 vector
<DNSRecord
> ret
;
3265 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3266 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3267 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3268 /* 13 NS + 1 RRSIG */
3269 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3270 BOOST_CHECK_EQUAL(queriesCount
, 2);
3272 /* again, to test the cache */
3274 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3275 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3276 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3277 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3278 BOOST_CHECK_EQUAL(queriesCount
, 2);
3281 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk
) {
3282 std::unique_ptr
<SyncRes
> sr
;
3285 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3288 const DNSName
target(".");
3289 testkeysset_t zskeys
;
3290 testkeysset_t kskeys
;
3292 /* Generate key material for "." */
3293 auto dckeZ
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3294 dckeZ
->create(dckeZ
->getBits());
3295 DNSSECPrivateKey ksk
;
3298 DSRecordContent kskds
= makeDSFromDNSKey(target
, ksk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3300 auto dckeK
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3301 dckeK
->create(dckeK
->getBits());
3302 DNSSECPrivateKey zsk
;
3305 DSRecordContent zskds
= makeDSFromDNSKey(target
, zsk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3307 kskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(ksk
, kskds
);
3308 zskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(zsk
, zskds
);
3310 /* Set the root DS */
3311 auto luaconfsCopy
= g_luaconfs
.getCopy();
3312 luaconfsCopy
.dsAnchors
.clear();
3313 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(kskds
);
3314 g_luaconfs
.setState(luaconfsCopy
);
3316 size_t queriesCount
= 0;
3318 sr
->setAsyncCallback([target
,&queriesCount
,zskeys
,kskeys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3321 if (domain
== target
&& type
== QType::NS
) {
3323 setLWResult(res
, 0, true, false, true);
3324 char addr
[] = "a.root-servers.net.";
3325 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3327 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3330 addRRSIG(zskeys
, res
->d_records
, domain
, 300);
3332 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3333 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3336 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3338 setLWResult(res
, 0, true, false, true);
3340 addDNSKEY(kskeys
, domain
, 300, res
->d_records
);
3341 addDNSKEY(zskeys
, domain
, 300, res
->d_records
);
3342 addRRSIG(kskeys
, res
->d_records
, domain
, 300);
3350 vector
<DNSRecord
> ret
;
3351 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3352 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3353 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3354 /* 13 NS + 1 RRSIG */
3355 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3356 BOOST_CHECK_EQUAL(queriesCount
, 2);
3358 /* again, to test the cache */
3360 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3361 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3362 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3363 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3364 BOOST_CHECK_EQUAL(queriesCount
, 2);
3367 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey
) {
3368 std::unique_ptr
<SyncRes
> sr
;
3371 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3374 const DNSName
target(".");
3377 auto luaconfsCopy
= g_luaconfs
.getCopy();
3378 luaconfsCopy
.dsAnchors
.clear();
3379 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3380 g_luaconfs
.setState(luaconfsCopy
);
3382 size_t queriesCount
= 0;
3384 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3387 if (domain
== target
&& type
== QType::NS
) {
3389 setLWResult(res
, 0, true, false, true);
3390 char addr
[] = "a.root-servers.net.";
3391 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3393 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3396 addRRSIG(keys
, res
->d_records
, domain
, 300);
3398 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3399 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3402 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3404 setLWResult(res
, 0, true, false, true);
3414 vector
<DNSRecord
> ret
;
3415 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3416 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3417 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3418 /* 13 NS + 1 RRSIG */
3419 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3420 BOOST_CHECK_EQUAL(queriesCount
, 2);
3422 /* again, to test the cache */
3424 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3425 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3426 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3427 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3428 BOOST_CHECK_EQUAL(queriesCount
, 2);
3431 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds
) {
3432 std::unique_ptr
<SyncRes
> sr
;
3435 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3438 const DNSName
target(".");
3439 testkeysset_t dskeys
;
3442 /* Generate key material for "." */
3443 auto dckeDS
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3444 dckeDS
->create(dckeDS
->getBits());
3445 DNSSECPrivateKey dskey
;
3446 dskey
.d_flags
= 257;
3447 dskey
.setKey(dckeDS
);
3448 DSRecordContent drc
= makeDSFromDNSKey(target
, dskey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3450 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3451 dcke
->create(dcke
->getBits());
3452 DNSSECPrivateKey dpk
;
3455 DSRecordContent uselessdrc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3457 dskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dskey
, drc
);
3458 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, uselessdrc
);
3460 /* Set the root DS */
3461 auto luaconfsCopy
= g_luaconfs
.getCopy();
3462 luaconfsCopy
.dsAnchors
.clear();
3463 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3464 g_luaconfs
.setState(luaconfsCopy
);
3466 size_t queriesCount
= 0;
3468 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3471 if (domain
== target
&& type
== QType::NS
) {
3473 setLWResult(res
, 0, true, false, true);
3474 char addr
[] = "a.root-servers.net.";
3475 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3477 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3480 addRRSIG(keys
, res
->d_records
, domain
, 300);
3482 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3483 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3486 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3488 setLWResult(res
, 0, true, false, true);
3490 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3491 addRRSIG(keys
, res
->d_records
, domain
, 300);
3499 vector
<DNSRecord
> ret
;
3500 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3501 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3502 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3503 /* 13 NS + 1 RRSIG */
3504 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3505 BOOST_CHECK_EQUAL(queriesCount
, 2);
3507 /* again, to test the cache */
3509 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3510 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3511 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3512 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3513 BOOST_CHECK_EQUAL(queriesCount
, 2);
3516 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey
) {
3517 std::unique_ptr
<SyncRes
> sr
;
3520 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3523 const DNSName
target(".");
3525 testkeysset_t rrsigkeys
;
3527 auto luaconfsCopy
= g_luaconfs
.getCopy();
3528 luaconfsCopy
.dsAnchors
.clear();
3529 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3530 g_luaconfs
.setState(luaconfsCopy
);
3532 auto dckeRRSIG
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3533 dckeRRSIG
->create(dckeRRSIG
->getBits());
3534 DNSSECPrivateKey rrsigkey
;
3535 rrsigkey
.d_flags
= 257;
3536 rrsigkey
.setKey(dckeRRSIG
);
3537 DSRecordContent rrsigds
= makeDSFromDNSKey(target
, rrsigkey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3539 rrsigkeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(rrsigkey
, rrsigds
);
3541 size_t queriesCount
= 0;
3543 sr
->setAsyncCallback([target
,&queriesCount
,keys
,rrsigkeys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3546 if (domain
== target
&& type
== QType::NS
) {
3548 setLWResult(res
, 0, true, false, true);
3549 char addr
[] = "a.root-servers.net.";
3550 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3552 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3555 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3557 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3558 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3561 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3563 setLWResult(res
, 0, true, false, true);
3565 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3566 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3574 vector
<DNSRecord
> ret
;
3575 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3576 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3577 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3578 /* 13 NS + 1 RRSIG */
3579 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3580 BOOST_CHECK_EQUAL(queriesCount
, 2);
3582 /* again, to test the cache */
3584 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3585 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3586 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3587 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3588 BOOST_CHECK_EQUAL(queriesCount
, 2);
3591 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig
) {
3592 std::unique_ptr
<SyncRes
> sr
;
3595 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3598 const DNSName
target(".");
3601 auto luaconfsCopy
= g_luaconfs
.getCopy();
3602 luaconfsCopy
.dsAnchors
.clear();
3603 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3604 g_luaconfs
.setState(luaconfsCopy
);
3606 size_t queriesCount
= 0;
3608 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3611 if (domain
== target
&& type
== QType::NS
) {
3613 setLWResult(res
, 0, true, false, true);
3614 char addr
[] = "a.root-servers.net.";
3615 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3617 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3622 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3623 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3626 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3628 setLWResult(res
, 0, true, false, true);
3630 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3631 addRRSIG(keys
, res
->d_records
, domain
, 300);
3639 vector
<DNSRecord
> ret
;
3640 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3641 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3642 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3643 /* 13 NS + 0 RRSIG */
3644 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3645 /* no RRSIG so no query for DNSKEYs */
3646 BOOST_CHECK_EQUAL(queriesCount
, 1);
3648 /* again, to test the cache */
3650 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3651 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3652 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3653 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3654 BOOST_CHECK_EQUAL(queriesCount
, 1);
3657 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm
) {
3658 std::unique_ptr
<SyncRes
> sr
;
3661 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3664 const DNSName
target(".");
3667 /* Generate key material for "." */
3668 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3669 dcke
->create(dcke
->getBits());
3670 DNSSECPrivateKey dpk
;
3673 /* Fake algorithm number (private) */
3674 dpk
.d_algorithm
= 253;
3676 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3677 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, drc
);
3678 /* Fake algorithm number (private) */
3679 drc
.d_algorithm
= 253;
3681 /* Set the root DS */
3682 auto luaconfsCopy
= g_luaconfs
.getCopy();
3683 luaconfsCopy
.dsAnchors
.clear();
3684 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3685 g_luaconfs
.setState(luaconfsCopy
);
3687 size_t queriesCount
= 0;
3689 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3692 if (domain
== target
&& type
== QType::NS
) {
3694 setLWResult(res
, 0, true, false, true);
3695 char addr
[] = "a.root-servers.net.";
3696 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3698 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3701 addRRSIG(keys
, res
->d_records
, domain
, 300);
3703 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3704 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3707 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3709 setLWResult(res
, 0, true, false, true);
3711 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3712 addRRSIG(keys
, res
->d_records
, domain
, 300);
3720 vector
<DNSRecord
> ret
;
3721 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3722 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3723 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3724 /* 13 NS + 1 RRSIG */
3725 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3726 /* no supported DS so no query for DNSKEYs */
3727 BOOST_CHECK_EQUAL(queriesCount
, 1);
3729 /* again, to test the cache */
3731 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3732 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3733 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3734 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3735 BOOST_CHECK_EQUAL(queriesCount
, 1);
3738 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest
) {
3739 std::unique_ptr
<SyncRes
> sr
;
3742 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3745 const DNSName
target(".");
3748 /* Generate key material for "." */
3749 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3750 dcke
->create(dcke
->getBits());
3751 DNSSECPrivateKey dpk
;
3754 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3755 /* Fake digest number (reserved) */
3756 drc
.d_digesttype
= 0;
3758 keys
[target
] = std::pair
<DNSSECPrivateKey
, DSRecordContent
>(dpk
, drc
);
3760 /* Set the root DS */
3761 auto luaconfsCopy
= g_luaconfs
.getCopy();
3762 luaconfsCopy
.dsAnchors
.clear();
3763 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3764 g_luaconfs
.setState(luaconfsCopy
);
3766 size_t queriesCount
= 0;
3768 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3771 if (domain
== target
&& type
== QType::NS
) {
3773 setLWResult(res
, 0, true, false, true);
3774 char addr
[] = "a.root-servers.net.";
3775 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3777 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3780 addRRSIG(keys
, res
->d_records
, domain
, 300);
3782 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3783 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3786 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3788 setLWResult(res
, 0, true, false, true);
3790 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3791 addRRSIG(keys
, res
->d_records
, domain
, 300);
3799 vector
<DNSRecord
> ret
;
3800 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3801 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3802 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3803 /* 13 NS + 1 RRSIG */
3804 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3805 /* no supported DS so no query for DNSKEYs */
3806 BOOST_CHECK_EQUAL(queriesCount
, 1);
3808 /* again, to test the cache */
3810 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3811 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3812 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3813 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3814 BOOST_CHECK_EQUAL(queriesCount
, 1);
3817 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig
) {
3818 std::unique_ptr
<SyncRes
> sr
;
3821 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3824 const DNSName
target(".");
3827 auto luaconfsCopy
= g_luaconfs
.getCopy();
3828 luaconfsCopy
.dsAnchors
.clear();
3829 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
3831 g_luaconfs
.setState(luaconfsCopy
);
3833 size_t queriesCount
= 0;
3835 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3838 if (domain
== target
&& type
== QType::NS
) {
3840 setLWResult(res
, 0, true, false, true);
3841 char addr
[] = "a.root-servers.net.";
3842 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3844 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3847 addRRSIG(keys
, res
->d_records
, domain
, 300, true);
3849 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3850 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3853 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3855 setLWResult(res
, 0, true, false, true);
3857 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3858 addRRSIG(keys
, res
->d_records
, domain
, 300);
3866 vector
<DNSRecord
> ret
;
3867 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3868 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3869 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3870 /* 13 NS + 1 RRSIG */
3871 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3872 BOOST_CHECK_EQUAL(queriesCount
, 2);
3874 /* again, to test the cache */
3876 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3877 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3878 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3879 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3880 BOOST_CHECK_EQUAL(queriesCount
, 2);
3883 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo
) {
3884 std::unique_ptr
<SyncRes
> sr
;
3887 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3890 const DNSName
target(".");
3893 auto luaconfsCopy
= g_luaconfs
.getCopy();
3894 luaconfsCopy
.dsAnchors
.clear();
3895 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
3897 g_luaconfs
.setState(luaconfsCopy
);
3899 size_t queriesCount
= 0;
3901 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3904 if (domain
== target
&& type
== QType::NS
) {
3906 setLWResult(res
, 0, true, false, true);
3907 char addr
[] = "a.root-servers.net.";
3908 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3910 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3913 /* FORCE WRONG ALGO */
3914 addRRSIG(keys
, res
->d_records
, domain
, 300, false, DNSSECKeeper::RSASHA256
);
3916 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3917 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3920 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3922 setLWResult(res
, 0, true, false, true);
3924 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3925 addRRSIG(keys
, res
->d_records
, domain
, 300);
3933 vector
<DNSRecord
> ret
;
3934 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3935 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3936 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3937 /* 13 NS + 1 RRSIG */
3938 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3939 BOOST_CHECK_EQUAL(queriesCount
, 2);
3941 /* again, to test the cache */
3943 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3944 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3945 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3946 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3947 BOOST_CHECK_EQUAL(queriesCount
, 2);
3950 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos
) {
3951 std::unique_ptr
<SyncRes
> sr
;
3954 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3957 const DNSName
target("powerdns.com.");
3958 const ComboAddress
targetAddr("192.0.2.42");
3961 auto luaconfsCopy
= g_luaconfs
.getCopy();
3962 luaconfsCopy
.dsAnchors
.clear();
3963 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
3964 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
3965 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384
, DNSSECKeeper::SHA384
, keys
);
3967 g_luaconfs
.setState(luaconfsCopy
);
3969 size_t queriesCount
= 0;
3971 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
3974 DNSName auth
= domain
;
3975 if (domain
== target
) {
3976 auth
= DNSName("powerdns.com.");
3978 if (type
== QType::DS
) {
3981 else if (type
== QType::DNSKEY
) {
3982 setLWResult(res
, 0, true, false, true);
3983 addDNSKEY(keys
, auth
, 300, res
->d_records
);
3984 addRRSIG(keys
, res
->d_records
, auth
, 300);
3988 if (isRootServer(ip
)) {
3989 setLWResult(res
, 0, false, false, true);
3990 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
3991 addDS(DNSName("com."), 300, res
->d_records
, keys
);
3992 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
3993 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
3996 else if (ip
== ComboAddress("192.0.2.1:53")) {
3997 if (domain
== DNSName("com.")) {
3998 setLWResult(res
, 0, true, false, true);
3999 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4000 addRRSIG(keys
, res
->d_records
, domain
, 300);
4001 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4002 addRRSIG(keys
, res
->d_records
, domain
, 300);
4005 setLWResult(res
, 0, false, false, true);
4006 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4007 addDS(auth
, 300, res
->d_records
, keys
);
4008 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4009 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4013 else if (ip
== ComboAddress("192.0.2.2:53")) {
4014 if (type
== QType::NS
) {
4015 setLWResult(res
, 0, true, false, true);
4016 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4017 addRRSIG(keys
, res
->d_records
, auth
, 300);
4018 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4019 addRRSIG(keys
, res
->d_records
, auth
, 300);
4022 setLWResult(res
, RCode::NoError
, true, false, true);
4023 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4024 addRRSIG(keys
, res
->d_records
, auth
, 300);
4033 vector
<DNSRecord
> ret
;
4034 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4035 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4036 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4037 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4038 BOOST_CHECK_EQUAL(queriesCount
, 8);
4040 /* again, to test the cache */
4042 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4043 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4044 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4045 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4046 BOOST_CHECK_EQUAL(queriesCount
, 8);
4049 BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns
) {
4050 std::unique_ptr
<SyncRes
> sr
;
4053 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4056 const DNSName
target("powerdns.com.");
4057 const ComboAddress
targetAddr("192.0.2.42");
4060 auto luaconfsCopy
= g_luaconfs
.getCopy();
4061 luaconfsCopy
.dsAnchors
.clear();
4062 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4063 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4064 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4065 g_luaconfs
.setState(luaconfsCopy
);
4067 size_t queriesCount
= 0;
4069 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4072 DNSName auth
= domain
;
4073 if (domain
== target
) {
4074 auth
= DNSName("powerdns.com.");
4076 if (type
== QType::DS
) {
4079 else if (type
== QType::DNSKEY
) {
4080 setLWResult(res
, 0, true, false, true);
4081 addDNSKEY(keys
, auth
, 300, res
->d_records
);
4082 addRRSIG(keys
, res
->d_records
, auth
, 300);
4086 if (isRootServer(ip
)) {
4087 setLWResult(res
, 0, false, false, true);
4088 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4089 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4090 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4091 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4094 else if (ip
== ComboAddress("192.0.2.1:53")) {
4095 if (domain
== DNSName("com.")) {
4096 setLWResult(res
, 0, true, false, true);
4097 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4098 addRRSIG(keys
, res
->d_records
, domain
, 300);
4099 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4100 addRRSIG(keys
, res
->d_records
, domain
, 300);
4103 setLWResult(res
, 0, false, false, true);
4104 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4105 addDS(auth
, 300, res
->d_records
, keys
);
4106 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4107 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4111 else if (ip
== ComboAddress("192.0.2.2:53")) {
4112 if (type
== QType::NS
) {
4113 setLWResult(res
, 0, true, false, true);
4114 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4115 addRRSIG(keys
, res
->d_records
, auth
, 300);
4116 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4117 addRRSIG(keys
, res
->d_records
, auth
, 300);
4120 setLWResult(res
, RCode::NoError
, true, false, true);
4121 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4122 addRRSIG(keys
, res
->d_records
, auth
, 300);
4131 vector
<DNSRecord
> ret
;
4132 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4133 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4134 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4135 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4136 BOOST_CHECK_EQUAL(queriesCount
, 8);
4138 /* again, to test the cache */
4140 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4141 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4142 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4143 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4144 BOOST_CHECK_EQUAL(queriesCount
, 8);
4146 /* this time we ask for the NS that should be in the cache, to check
4147 the validation status */
4149 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4150 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4151 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4152 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4153 BOOST_CHECK_EQUAL(queriesCount
, 8);
4157 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns
) {
4158 std::unique_ptr
<SyncRes
> sr
;
4161 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4164 const DNSName
target("powerdns.com.");
4165 const ComboAddress
targetAddr("192.0.2.42");
4168 auto luaconfsCopy
= g_luaconfs
.getCopy();
4169 luaconfsCopy
.dsAnchors
.clear();
4170 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4171 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4172 g_luaconfs
.setState(luaconfsCopy
);
4174 size_t queriesCount
= 0;
4176 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4179 DNSName auth
= domain
;
4180 if (domain
== target
) {
4181 auth
= DNSName("powerdns.com.");
4183 if (type
== QType::DS
) {
4186 else if (type
== QType::DNSKEY
) {
4187 setLWResult(res
, 0, true, false, true);
4188 addDNSKEY(keys
, auth
, 300, res
->d_records
);
4189 addRRSIG(keys
, res
->d_records
, auth
, 300);
4193 if (isRootServer(ip
)) {
4194 setLWResult(res
, 0, false, false, true);
4195 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4196 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4197 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4198 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4201 else if (ip
== ComboAddress("192.0.2.1:53")) {
4202 if (domain
== DNSName("com.")) {
4203 setLWResult(res
, 0, true, false, true);
4204 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4205 addRRSIG(keys
, res
->d_records
, domain
, 300);
4206 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4207 addRRSIG(keys
, res
->d_records
, domain
, 300);
4210 setLWResult(res
, 0, false, false, true);
4211 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4213 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
4214 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4215 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4219 else if (ip
== ComboAddress("192.0.2.2:53")) {
4220 if (type
== QType::NS
) {
4221 setLWResult(res
, 0, true, false, true);
4222 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4223 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4226 setLWResult(res
, RCode::NoError
, true, false, true);
4227 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4236 vector
<DNSRecord
> ret
;
4237 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4238 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4239 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4240 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4241 BOOST_CHECK_EQUAL(queriesCount
, 7);
4243 /* again, to test the cache */
4245 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4246 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4247 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4248 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4249 BOOST_CHECK_EQUAL(queriesCount
, 7);
4251 /* this time we ask for the NS that should be in the cache, to check
4252 the validation status */
4254 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4255 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4256 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4257 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4258 BOOST_CHECK_EQUAL(queriesCount
, 7);
4261 BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta
) {
4262 std::unique_ptr
<SyncRes
> sr
;
4265 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4268 const DNSName
target("powerdns.com.");
4269 const ComboAddress
targetAddr("192.0.2.42");
4272 auto luaconfsCopy
= g_luaconfs
.getCopy();
4273 luaconfsCopy
.dsAnchors
.clear();
4274 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4275 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4276 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4278 /* Add a NTA for "powerdns.com" */
4279 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4281 g_luaconfs
.setState(luaconfsCopy
);
4283 size_t queriesCount
= 0;
4285 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4288 DNSName auth
= domain
;
4289 if (domain
== target
) {
4290 auth
= DNSName("powerdns.com.");
4292 if (type
== QType::DS
) {
4295 else if (type
== QType::DNSKEY
) {
4296 setLWResult(res
, 0, true, false, true);
4297 addDNSKEY(keys
, auth
, 300, res
->d_records
);
4298 addRRSIG(keys
, res
->d_records
, auth
, 300);
4302 if (isRootServer(ip
)) {
4303 setLWResult(res
, 0, false, false, true);
4304 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4305 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4306 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4307 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4310 else if (ip
== ComboAddress("192.0.2.1:53")) {
4311 if (domain
== DNSName("com.")) {
4312 setLWResult(res
, 0, true, false, true);
4313 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4314 addRRSIG(keys
, res
->d_records
, domain
, 300);
4315 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4316 addRRSIG(keys
, res
->d_records
, domain
, 300);
4319 setLWResult(res
, 0, false, false, true);
4320 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4321 addDS(auth
, 300, res
->d_records
, keys
);
4322 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4323 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4327 else if (ip
== ComboAddress("192.0.2.2:53")) {
4328 if (type
== QType::NS
) {
4329 setLWResult(res
, 0, true, false, true);
4330 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4331 addRRSIG(keys
, res
->d_records
, auth
, 300);
4332 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4333 addRRSIG(keys
, res
->d_records
, auth
, 300);
4336 setLWResult(res
, RCode::NoError
, true, false, true);
4337 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4338 addRRSIG(keys
, res
->d_records
, auth
, 300);
4347 vector
<DNSRecord
> ret
;
4348 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4349 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4350 /* Should be insecure because of the NTA */
4351 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4352 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4353 BOOST_CHECK_EQUAL(queriesCount
, 7);
4355 /* again, to test the cache */
4357 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4358 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4359 /* Should be insecure because of the NTA */
4360 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4361 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4362 BOOST_CHECK_EQUAL(queriesCount
, 7);
4365 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta
) {
4366 std::unique_ptr
<SyncRes
> sr
;
4369 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4372 const DNSName
target("powerdns.com.");
4373 const ComboAddress
targetAddr("192.0.2.42");
4376 auto luaconfsCopy
= g_luaconfs
.getCopy();
4377 luaconfsCopy
.dsAnchors
.clear();
4378 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4379 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4380 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4382 /* Add a NTA for "powerdns.com" */
4383 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4385 g_luaconfs
.setState(luaconfsCopy
);
4387 size_t queriesCount
= 0;
4389 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4392 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4393 setLWResult(res
, 0, false, false, true);
4394 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4398 if (isRootServer(ip
)) {
4399 setLWResult(res
, 0, false, false, true);
4400 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4401 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4404 else if (ip
== ComboAddress("192.0.2.1:53")) {
4405 if (domain
== DNSName("com.")) {
4406 setLWResult(res
, 0, true, false, true);
4407 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4408 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4411 setLWResult(res
, 0, false, false, true);
4412 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4413 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4417 else if (ip
== ComboAddress("192.0.2.2:53")) {
4418 if (type
== QType::NS
) {
4419 setLWResult(res
, 0, true, false, true);
4420 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4421 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4424 setLWResult(res
, RCode::NoError
, true, false, true);
4425 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4434 /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
4435 vector
<DNSRecord
> ret
;
4436 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4437 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4438 /* Should be insecure because of the NTA */
4439 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4440 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4441 /* and a such, no query for the DNSKEYs */
4442 BOOST_CHECK_EQUAL(queriesCount
, 6);
4444 /* again, to test the cache */
4446 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4447 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4448 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4449 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4450 BOOST_CHECK_EQUAL(queriesCount
, 6);
4453 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec
) {
4454 std::unique_ptr
<SyncRes
> sr
;
4457 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4460 const DNSName
target("powerdns.com.");
4463 auto luaconfsCopy
= g_luaconfs
.getCopy();
4464 luaconfsCopy
.dsAnchors
.clear();
4465 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4466 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4467 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4469 g_luaconfs
.setState(luaconfsCopy
);
4471 size_t queriesCount
= 0;
4473 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4476 if (type
== QType::DS
) {
4479 else if (type
== QType::DNSKEY
) {
4480 setLWResult(res
, 0, true, false, true);
4481 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4482 addRRSIG(keys
, res
->d_records
, domain
, 300);
4486 if (isRootServer(ip
)) {
4487 setLWResult(res
, 0, false, false, true);
4488 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4489 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4490 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4491 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4494 else if (ip
== ComboAddress("192.0.2.1:53")) {
4495 if (domain
== DNSName("com.")) {
4496 setLWResult(res
, 0, true, false, true);
4497 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4498 addRRSIG(keys
, res
->d_records
, domain
, 300);
4499 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4500 addRRSIG(keys
, res
->d_records
, domain
, 300);
4503 setLWResult(res
, 0, false, false, true);
4504 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4505 addDS(domain
, 300, res
->d_records
, keys
);
4506 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4507 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4511 else if (ip
== ComboAddress("192.0.2.2:53")) {
4512 if (type
== QType::NS
) {
4513 setLWResult(res
, 0, true, false, true);
4514 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4515 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4516 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4517 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4520 setLWResult(res
, 0, true, false, true);
4521 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4522 addRRSIG(keys
, res
->d_records
, domain
, 300);
4523 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
4524 addRRSIG(keys
, res
->d_records
, domain
, 300);
4533 vector
<DNSRecord
> ret
;
4534 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4535 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4536 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4537 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4538 BOOST_CHECK_EQUAL(queriesCount
, 8);
4540 /* again, to test the cache */
4542 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4543 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4544 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4545 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4546 BOOST_CHECK_EQUAL(queriesCount
, 8);
4549 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec
) {
4550 std::unique_ptr
<SyncRes
> sr
;
4553 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4556 const DNSName
target("nx.powerdns.com.");
4559 auto luaconfsCopy
= g_luaconfs
.getCopy();
4560 luaconfsCopy
.dsAnchors
.clear();
4561 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4562 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4563 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4565 g_luaconfs
.setState(luaconfsCopy
);
4567 size_t queriesCount
= 0;
4569 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4572 DNSName auth
= domain
;
4573 if (domain
== target
) {
4574 auth
= DNSName("powerdns.com.");
4576 if (type
== QType::DS
) {
4579 else if (type
== QType::DNSKEY
) {
4580 setLWResult(res
, 0, true, false, true);
4581 addDNSKEY(keys
, auth
, 300, res
->d_records
);
4582 addRRSIG(keys
, res
->d_records
, auth
, 300);
4586 if (isRootServer(ip
)) {
4587 setLWResult(res
, 0, false, false, true);
4588 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4589 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4590 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4591 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4594 else if (ip
== ComboAddress("192.0.2.1:53")) {
4595 if (domain
== DNSName("com.")) {
4596 setLWResult(res
, 0, true, false, true);
4597 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4598 addRRSIG(keys
, res
->d_records
, domain
, 300);
4599 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4600 addRRSIG(keys
, res
->d_records
, domain
, 300);
4603 setLWResult(res
, 0, false, false, true);
4604 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4605 addDS(auth
, 300, res
->d_records
, keys
);
4606 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4607 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4611 else if (ip
== ComboAddress("192.0.2.2:53")) {
4612 if (type
== QType::NS
) {
4613 setLWResult(res
, 0, true, false, true);
4614 if (domain
== DNSName("powerdns.com.")) {
4615 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4616 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4617 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4618 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4621 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4622 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4623 addNSECRecordToLW(DNSName("nx.powerdns.com."), DNSName("nz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4624 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4628 setLWResult(res
, RCode::NXDomain
, true, false, true);
4629 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4630 addRRSIG(keys
, res
->d_records
, auth
, 300);
4631 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4632 addRRSIG(keys
, res
->d_records
, auth
, 300);
4641 vector
<DNSRecord
> ret
;
4642 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4643 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
4644 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4645 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4646 BOOST_CHECK_EQUAL(queriesCount
, 9);
4648 /* again, to test the cache */
4650 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4651 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
4652 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4653 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4654 BOOST_CHECK_EQUAL(queriesCount
, 9);
4657 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard
) {
4658 std::unique_ptr
<SyncRes
> sr
;
4661 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4664 const DNSName
target("www.powerdns.com.");
4667 auto luaconfsCopy
= g_luaconfs
.getCopy();
4668 luaconfsCopy
.dsAnchors
.clear();
4669 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4670 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4671 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4673 g_luaconfs
.setState(luaconfsCopy
);
4675 size_t queriesCount
= 0;
4677 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4680 if (type
== QType::DS
) {
4683 else if (type
== QType::DNSKEY
) {
4684 setLWResult(res
, 0, true, false, true);
4685 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4686 addRRSIG(keys
, res
->d_records
, domain
, 300);
4690 if (isRootServer(ip
)) {
4691 setLWResult(res
, 0, false, false, true);
4692 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4693 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4694 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4695 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4698 else if (ip
== ComboAddress("192.0.2.1:53")) {
4699 if (domain
== DNSName("com.")) {
4700 setLWResult(res
, 0, true, false, true);
4701 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4702 addRRSIG(keys
, res
->d_records
, domain
, 300);
4703 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4704 addRRSIG(keys
, res
->d_records
, domain
, 300);
4707 setLWResult(res
, 0, false, false, true);
4708 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4709 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
4710 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4711 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4715 else if (ip
== ComboAddress("192.0.2.2:53")) {
4716 setLWResult(res
, 0, true, false, true);
4717 if (type
== QType::NS
) {
4718 if (domain
== DNSName("powerdns.com.")) {
4719 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4720 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4721 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4722 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4725 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4726 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4727 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4728 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4732 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
4733 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
4734 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4735 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4744 vector
<DNSRecord
> ret
;
4745 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4746 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4747 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4748 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4749 BOOST_CHECK_EQUAL(queriesCount
, 9);
4751 /* again, to test the cache */
4753 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4754 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4755 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4756 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4757 BOOST_CHECK_EQUAL(queriesCount
, 9);
4760 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure
) {
4761 std::unique_ptr
<SyncRes
> sr
;
4764 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4767 const DNSName
target("www.powerdns.com.");
4770 auto luaconfsCopy
= g_luaconfs
.getCopy();
4771 luaconfsCopy
.dsAnchors
.clear();
4772 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4773 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4774 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4776 g_luaconfs
.setState(luaconfsCopy
);
4778 size_t queriesCount
= 0;
4779 size_t dsQueriesCount
= 0;
4781 sr
->setAsyncCallback([target
,&queriesCount
,&dsQueriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4784 if (type
== QType::DS
) {
4785 DNSName
auth(domain
);
4789 setLWResult(res
, 0, true, false, true);
4790 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
4791 addRRSIG(keys
, res
->d_records
, auth
, 300);
4794 else if (type
== QType::DNSKEY
) {
4795 setLWResult(res
, 0, true, false, true);
4796 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4797 addRRSIG(keys
, res
->d_records
, domain
, 300);
4801 if (isRootServer(ip
)) {
4802 setLWResult(res
, 0, false, false, true);
4803 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4804 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4805 /* No DS on referral, and no denial of the DS either */
4808 else if (ip
== ComboAddress("192.0.2.1:53")) {
4809 if (domain
== DNSName("com.")) {
4810 setLWResult(res
, 0, true, false, true);
4811 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4812 addRRSIG(keys
, res
->d_records
, domain
, 300);
4813 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4814 addRRSIG(keys
, res
->d_records
, domain
, 300);
4817 setLWResult(res
, 0, false, false, true);
4818 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4819 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4820 /* No DS on referral, and no denial of the DS either */
4824 else if (ip
== ComboAddress("192.0.2.2:53")) {
4825 setLWResult(res
, 0, true, false, true);
4826 if (type
== QType::NS
) {
4827 if (domain
== DNSName("powerdns.com.")) {
4828 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4829 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4830 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4831 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4834 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4835 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4836 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4837 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4841 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
4842 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4852 vector
<DNSRecord
> ret
;
4853 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4854 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4855 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4856 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4857 BOOST_CHECK_EQUAL(queriesCount
, 11);
4858 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
4860 /* again, to test the cache */
4862 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4863 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4864 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4865 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4866 BOOST_CHECK_EQUAL(queriesCount
, 11);
4867 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
4870 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure
) {
4871 std::unique_ptr
<SyncRes
> sr
;
4874 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4877 const DNSName
target("www.powerdns.com.");
4880 auto luaconfsCopy
= g_luaconfs
.getCopy();
4881 luaconfsCopy
.dsAnchors
.clear();
4882 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4883 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4885 g_luaconfs
.setState(luaconfsCopy
);
4887 size_t queriesCount
= 0;
4888 size_t dsQueriesCount
= 0;
4890 sr
->setAsyncCallback([target
,&queriesCount
,&dsQueriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
4893 if (type
== QType::DS
) {
4894 DNSName
auth(domain
);
4898 setLWResult(res
, 0, true, false, true);
4899 if (domain
== DNSName("com.")) {
4900 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
4903 addRecordToLW(res
, "com.", QType::SOA
, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4904 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4905 addNSECRecordToLW(domain
, DNSName("powerdnt.com."), { QType::NS
}, 600, res
->d_records
);
4907 addRRSIG(keys
, res
->d_records
, auth
, 300);
4910 else if (type
== QType::DNSKEY
) {
4911 setLWResult(res
, 0, true, false, true);
4912 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4913 addRRSIG(keys
, res
->d_records
, domain
, 300);
4917 if (isRootServer(ip
)) {
4918 setLWResult(res
, 0, false, false, true);
4919 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4920 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4921 /* No DS on referral, and no denial of the DS either */
4924 else if (ip
== ComboAddress("192.0.2.1:53")) {
4925 if (domain
== DNSName("com.")) {
4926 setLWResult(res
, 0, true, false, true);
4927 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4928 addRRSIG(keys
, res
->d_records
, domain
, 300);
4929 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4930 addRRSIG(keys
, res
->d_records
, domain
, 300);
4933 setLWResult(res
, 0, false, false, true);
4934 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4935 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4936 /* No DS on referral, and no denial of the DS either */
4940 else if (ip
== ComboAddress("192.0.2.2:53")) {
4941 setLWResult(res
, 0, true, false, true);
4942 if (type
== QType::NS
) {
4943 if (domain
== DNSName("powerdns.com.")) {
4944 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4945 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4948 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4952 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
4961 vector
<DNSRecord
> ret
;
4962 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4963 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4964 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4965 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4966 BOOST_CHECK_EQUAL(queriesCount
, 10);
4967 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
4969 /* again, to test the cache */
4971 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4972 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4973 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4974 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4975 BOOST_CHECK_EQUAL(queriesCount
, 10);
4976 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
4979 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec
) {
4980 std::unique_ptr
<SyncRes
> sr
;
4983 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4986 const DNSName
target("powerdns.com.");
4989 auto luaconfsCopy
= g_luaconfs
.getCopy();
4990 luaconfsCopy
.dsAnchors
.clear();
4991 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4992 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4993 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4995 g_luaconfs
.setState(luaconfsCopy
);
4997 size_t queriesCount
= 0;
4999 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5002 if (type
== QType::DS
) {
5005 else if (type
== QType::DNSKEY
) {
5006 setLWResult(res
, 0, true, false, true);
5007 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5008 addRRSIG(keys
, res
->d_records
, domain
, 300);
5012 if (isRootServer(ip
)) {
5013 setLWResult(res
, 0, false, false, true);
5014 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5015 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5016 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5017 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5020 else if (ip
== ComboAddress("192.0.2.1:53")) {
5021 if (domain
== DNSName("com.")) {
5022 setLWResult(res
, 0, true, false, true);
5023 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
5024 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5025 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5028 setLWResult(res
, 0, false, false, true);
5029 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5030 addDS(domain
, 300, res
->d_records
, keys
);
5031 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5032 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5036 else if (ip
== ComboAddress("192.0.2.2:53")) {
5037 setLWResult(res
, 0, true, false, true);
5038 if (type
== QType::NS
) {
5039 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5040 addRRSIG(keys
, res
->d_records
, domain
, 300);
5043 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5044 addRRSIG(keys
, res
->d_records
, domain
, 300);
5045 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
5046 /* NO RRSIG for the NSEC record! */
5055 /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
5056 vector
<DNSRecord
> ret
;
5057 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5058 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5059 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5060 BOOST_CHECK_EQUAL(ret
.size(), 3);
5061 BOOST_CHECK_EQUAL(queriesCount
, 8);
5063 /* again, to test the cache */
5065 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5066 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5067 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5068 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5069 BOOST_CHECK_EQUAL(queriesCount
, 8);
5072 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec
) {
5073 std::unique_ptr
<SyncRes
> sr
;
5076 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5079 const DNSName
target("powerdns.com.");
5082 auto luaconfsCopy
= g_luaconfs
.getCopy();
5083 luaconfsCopy
.dsAnchors
.clear();
5084 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5085 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5086 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5088 g_luaconfs
.setState(luaconfsCopy
);
5090 size_t queriesCount
= 0;
5092 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5095 if (type
== QType::DS
) {
5098 else if (type
== QType::DNSKEY
) {
5099 setLWResult(res
, 0, true, false, true);
5100 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5101 addRRSIG(keys
, res
->d_records
, domain
, 300);
5105 if (isRootServer(ip
)) {
5106 setLWResult(res
, 0, false, false, true);
5107 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5108 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5109 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5110 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5113 else if (ip
== ComboAddress("192.0.2.1:53")) {
5114 if (domain
== DNSName("com.")) {
5115 setLWResult(res
, 0, true, false, true);
5116 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
5117 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5118 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5121 setLWResult(res
, 0, false, false, true);
5122 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5123 addDS(domain
, 300, res
->d_records
, keys
);
5124 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5125 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5129 else if (ip
== ComboAddress("192.0.2.2:53")) {
5130 setLWResult(res
, 0, true, false, true);
5131 if (type
== QType::NS
) {
5132 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5133 addRRSIG(keys
, res
->d_records
, domain
, 300);
5136 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5137 addRRSIG(keys
, res
->d_records
, domain
, 300);
5139 /* NO NSEC record! */
5148 /* no NSEC record in a secure zone, should be Bogus! */
5149 vector
<DNSRecord
> ret
;
5150 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5151 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5152 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5153 BOOST_CHECK_EQUAL(ret
.size(), 2);
5154 BOOST_CHECK_EQUAL(queriesCount
, 8);
5156 /* again, to test the cache */
5158 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5159 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5160 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5161 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5162 BOOST_CHECK_EQUAL(queriesCount
, 8);
5165 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure
) {
5166 std::unique_ptr
<SyncRes
> sr
;
5169 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5172 const DNSName
target("powerdns.com.");
5173 const ComboAddress
targetAddr("192.0.2.42");
5176 auto luaconfsCopy
= g_luaconfs
.getCopy();
5177 luaconfsCopy
.dsAnchors
.clear();
5178 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5179 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5181 g_luaconfs
.setState(luaconfsCopy
);
5183 size_t queriesCount
= 0;
5185 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5188 if (type
== QType::DS
) {
5189 if (domain
== target
) {
5190 setLWResult(res
, 0, false, false, true);
5191 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5192 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5193 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5197 else if (type
== QType::DNSKEY
) {
5198 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
5199 setLWResult(res
, 0, true, false, true);
5200 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5201 addRRSIG(keys
, res
->d_records
, domain
, 300);
5205 setLWResult(res
, 0, false, false, true);
5206 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5211 if (isRootServer(ip
)) {
5212 setLWResult(res
, 0, false, false, true);
5213 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5214 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5215 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5216 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5219 else if (ip
== ComboAddress("192.0.2.1:53")) {
5220 if (domain
== DNSName("com.")) {
5221 setLWResult(res
, 0, true, false, true);
5222 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
5223 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5224 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5227 setLWResult(res
, 0, false, false, true);
5228 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5230 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5231 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5232 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5236 else if (ip
== ComboAddress("192.0.2.2:53")) {
5237 setLWResult(res
, 0, true, false, true);
5238 if (type
== QType::NS
) {
5239 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5242 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString());
5251 vector
<DNSRecord
> ret
;
5252 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5253 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5254 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5255 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5256 BOOST_CHECK(ret
[0].d_type
== QType::A
);
5257 /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
5258 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
5260 BOOST_CHECK_EQUAL(queriesCount
, 7);
5262 /* again, to test the cache */
5264 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5265 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5266 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5267 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5268 BOOST_CHECK(ret
[0].d_type
== QType::A
);
5269 BOOST_CHECK_EQUAL(queriesCount
, 7);
5272 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut
) {
5273 std::unique_ptr
<SyncRes
> sr
;
5276 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5279 const DNSName
target("www.sub.powerdns.com.");
5280 const ComboAddress
targetAddr("192.0.2.42");
5283 auto luaconfsCopy
= g_luaconfs
.getCopy();
5284 luaconfsCopy
.dsAnchors
.clear();
5285 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5286 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5287 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5289 g_luaconfs
.setState(luaconfsCopy
);
5291 size_t queriesCount
= 0;
5293 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5296 if (type
== QType::DS
) {
5297 if (domain
== DNSName("sub.powerdns.com.")) {
5298 setLWResult(res
, 0, false, false, true);
5299 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5300 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5301 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5302 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5305 else if (domain
== DNSName("www.sub.powerdns.com.")) {
5306 setLWResult(res
, 0, false, false, true);
5307 addRecordToLW(res
, DNSName("sub.powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5311 else if (type
== QType::DNSKEY
) {
5312 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
5313 setLWResult(res
, 0, true, false, true);
5314 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5315 addRRSIG(keys
, res
->d_records
, domain
, 300);
5319 setLWResult(res
, 0, false, false, true);
5320 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5325 if (isRootServer(ip
)) {
5326 setLWResult(res
, 0, false, false, true);
5327 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5328 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5329 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5330 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5333 else if (ip
== ComboAddress("192.0.2.1:53")) {
5334 if (domain
== DNSName("com.")) {
5335 setLWResult(res
, 0, true, false, true);
5336 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
5337 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5338 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5341 setLWResult(res
, 0, false, false, true);
5342 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5343 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5344 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5345 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5349 else if (ip
== ComboAddress("192.0.2.2:53")) {
5350 setLWResult(res
, 0, true, false, true);
5351 if (type
== QType::NS
) {
5352 if (domain
== DNSName("www.sub.powerdns.com.")) {
5353 addRecordToLW(res
, DNSName("sub.powerdns.com"), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5355 else if (domain
== DNSName("sub.powerdns.com.")) {
5356 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5358 else if (domain
== DNSName("powerdns.com.")) {
5359 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5360 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5363 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
5372 vector
<DNSRecord
> ret
;
5373 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5374 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5375 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5376 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5377 BOOST_CHECK(ret
[0].d_type
== QType::A
);
5378 BOOST_CHECK_EQUAL(queriesCount
, 11);
5380 /* again, to test the cache */
5382 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5383 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5384 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5385 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5386 BOOST_CHECK(ret
[0].d_type
== QType::A
);
5387 BOOST_CHECK_EQUAL(queriesCount
, 11);
5390 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut
) {
5391 std::unique_ptr
<SyncRes
> sr
;
5394 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5397 const DNSName
target("www.sub.powerdns.com.");
5398 const ComboAddress
targetAddr("192.0.2.42");
5401 auto luaconfsCopy
= g_luaconfs
.getCopy();
5402 luaconfsCopy
.dsAnchors
.clear();
5403 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5404 /* No key material for .com */
5405 /* But TA for sub.powerdns.com. */
5406 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5407 luaconfsCopy
.dsAnchors
[DNSName("sub.powerdns.com.")].insert(keys
[DNSName("sub.powerdns.com.")].second
);
5408 g_luaconfs
.setState(luaconfsCopy
);
5410 size_t queriesCount
= 0;
5412 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5415 if (type
== QType::DS
) {
5416 if (domain
== DNSName("www.sub.powerdns.com")) {
5417 setLWResult(res
, 0, false, false, true);
5418 addRecordToLW(res
, DNSName("sub.powerdns.com"), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5419 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
5420 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
5421 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
5424 setLWResult(res
, 0, false, false, true);
5425 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5429 else if (type
== QType::DNSKEY
) {
5430 if (domain
== g_rootdnsname
|| domain
== DNSName("sub.powerdns.com.")) {
5431 setLWResult(res
, 0, true, false, true);
5432 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5433 addRRSIG(keys
, res
->d_records
, domain
, 300);
5438 if (isRootServer(ip
)) {
5439 setLWResult(res
, 0, false, false, true);
5440 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5442 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
5443 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5444 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5447 else if (ip
== ComboAddress("192.0.2.1:53")) {
5448 if (domain
== DNSName("com.")) {
5449 setLWResult(res
, 0, true, false, true);
5450 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
5451 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5453 else if (domain
== DNSName("powerdns.com.")) {
5454 setLWResult(res
, 0, false, false, true);
5455 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5456 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5460 else if (ip
== ComboAddress("192.0.2.2:53")) {
5461 setLWResult(res
, 0, true, false, true);
5462 if (type
== QType::NS
) {
5463 if (domain
== DNSName("www.sub.powerdns.com.")) {
5464 addRecordToLW(res
, DNSName("sub.powerdns.com"), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5465 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
5466 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
5467 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
5469 else if (domain
== DNSName("sub.powerdns.com.")) {
5470 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5471 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
5473 else if (domain
== DNSName("powerdns.com.")) {
5474 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5477 else if (domain
== DNSName("www.sub.powerdns.com.")) {
5478 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
5479 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
5488 vector
<DNSRecord
> ret
;
5489 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5490 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5491 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5492 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5493 BOOST_CHECK(ret
[0].d_type
== QType::A
);
5494 BOOST_CHECK_EQUAL(queriesCount
, 9);
5496 /* again, to test the cache */
5498 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5499 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5500 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5501 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5502 BOOST_CHECK(ret
[0].d_type
== QType::A
);
5503 BOOST_CHECK_EQUAL(queriesCount
, 9);
5506 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata
) {
5507 std::unique_ptr
<SyncRes
> sr
;
5510 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5513 const DNSName
target("powerdns.com.");
5516 auto luaconfsCopy
= g_luaconfs
.getCopy();
5517 luaconfsCopy
.dsAnchors
.clear();
5518 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5519 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5521 g_luaconfs
.setState(luaconfsCopy
);
5523 size_t queriesCount
= 0;
5525 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5528 if (type
== QType::DS
) {
5529 if (domain
== target
) {
5530 setLWResult(res
, 0, false, false, true);
5531 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5532 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5533 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5537 else if (type
== QType::DNSKEY
) {
5538 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
5539 setLWResult(res
, 0, true, false, true);
5540 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5541 addRRSIG(keys
, res
->d_records
, domain
, 300);
5545 setLWResult(res
, 0, false, false, true);
5546 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5551 if (isRootServer(ip
)) {
5552 setLWResult(res
, 0, false, false, true);
5553 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5554 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5555 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5556 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5559 else if (ip
== ComboAddress("192.0.2.1:53")) {
5560 if (domain
== DNSName("com.")) {
5561 setLWResult(res
, 0, true, false, true);
5562 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5563 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5564 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5565 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5568 setLWResult(res
, 0, false, false, true);
5569 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5571 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5572 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5573 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5577 else if (ip
== ComboAddress("192.0.2.2:53")) {
5578 if (type
== QType::NS
) {
5579 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5580 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5583 setLWResult(res
, 0, true, false, true);
5584 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5593 vector
<DNSRecord
> ret
;
5594 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5595 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5596 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5597 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5598 /* 4 NS (com from root, com from com, powerdns.com from com,
5599 powerdns.com from powerdns.com)
5600 2 DNSKEY (. and com., none for powerdns.com because no DS)
5603 BOOST_CHECK_EQUAL(queriesCount
, 7);
5605 /* again, to test the cache */
5607 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5608 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5609 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5610 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5611 BOOST_CHECK_EQUAL(queriesCount
, 7);
5614 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname
) {
5615 std::unique_ptr
<SyncRes
> sr
;
5618 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5621 const DNSName
target("powerdns.com.");
5622 const DNSName
targetCName("power-dns.com.");
5623 const ComboAddress
targetCNameAddr("192.0.2.42");
5626 auto luaconfsCopy
= g_luaconfs
.getCopy();
5627 luaconfsCopy
.dsAnchors
.clear();
5628 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5629 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5630 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5631 g_luaconfs
.setState(luaconfsCopy
);
5633 size_t queriesCount
= 0;
5635 sr
->setAsyncCallback([target
,targetCName
,targetCNameAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5638 if (type
== QType::DS
) {
5639 if (domain
== target
) {
5640 setLWResult(res
, 0, false, false, true);
5641 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5642 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
5643 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5647 else if (type
== QType::DNSKEY
) {
5648 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
5649 setLWResult(res
, 0, true, false, true);
5650 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5651 addRRSIG(keys
, res
->d_records
, domain
, 300);
5655 setLWResult(res
, 0, false, false, true);
5656 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5661 if (isRootServer(ip
)) {
5662 setLWResult(res
, 0, false, false, true);
5663 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5664 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5665 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5666 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5669 else if (ip
== ComboAddress("192.0.2.1:53")) {
5670 setLWResult(res
, 0, false, false, true);
5671 if (domain
== DNSName("com.")) {
5672 setLWResult(res
, 0, true, false, true);
5673 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5674 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5675 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5676 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5679 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5680 if (domain
== DNSName("powerdns.com.")) {
5681 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5683 else if (domain
== targetCName
) {
5684 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
5686 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5687 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5692 else if (ip
== ComboAddress("192.0.2.2:53")) {
5693 setLWResult(res
, 0, true, false, true);
5695 if (type
== QType::NS
) {
5696 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5697 if (domain
== DNSName("powerdns.com.")) {
5698 addRRSIG(keys
, res
->d_records
, domain
, 300);
5700 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5701 if (domain
== DNSName("powerdns.com.")) {
5702 addRRSIG(keys
, res
->d_records
, domain
, 300);
5706 if (domain
== DNSName("powerdns.com.")) {
5707 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
5708 addRRSIG(keys
, res
->d_records
, domain
, 300);
5710 else if (domain
== targetCName
) {
5711 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
5722 vector
<DNSRecord
> ret
;
5723 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5724 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5725 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5726 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5727 BOOST_CHECK_EQUAL(queriesCount
, 11);
5729 /* again, to test the cache */
5731 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5732 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5733 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5734 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5735 BOOST_CHECK_EQUAL(queriesCount
, 11);
5738 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname
) {
5739 std::unique_ptr
<SyncRes
> sr
;
5742 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5745 const DNSName
target("power-dns.com.");
5746 const DNSName
targetCName("powerdns.com.");
5747 const ComboAddress
targetCNameAddr("192.0.2.42");
5750 auto luaconfsCopy
= g_luaconfs
.getCopy();
5751 luaconfsCopy
.dsAnchors
.clear();
5752 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5753 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5754 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5755 g_luaconfs
.setState(luaconfsCopy
);
5757 size_t queriesCount
= 0;
5759 sr
->setAsyncCallback([target
,targetCName
,targetCNameAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5762 if (type
== QType::DS
) {
5763 if (domain
== DNSName("power-dns.com.")) {
5764 setLWResult(res
, 0, false, false, true);
5765 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5766 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
5767 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5771 else if (type
== QType::DNSKEY
) {
5772 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
5773 setLWResult(res
, 0, true, false, true);
5774 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5775 addRRSIG(keys
, res
->d_records
, domain
, 300);
5779 setLWResult(res
, 0, false, false, true);
5780 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5785 if (isRootServer(ip
)) {
5786 setLWResult(res
, 0, false, false, true);
5787 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5788 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5789 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5790 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5793 else if (ip
== ComboAddress("192.0.2.1:53")) {
5794 if (domain
== DNSName("com.")) {
5795 setLWResult(res
, 0, true, false, true);
5796 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5797 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5798 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5799 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5801 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
5802 setLWResult(res
, 0, false, false, true);
5803 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5804 if (domain
== targetCName
) {
5805 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5807 else if (domain
== target
) {
5808 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
5810 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5811 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5815 else if (ip
== ComboAddress("192.0.2.2:53")) {
5816 setLWResult(res
, 0, true, false, true);
5817 if (type
== QType::NS
) {
5818 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5819 if (domain
== DNSName("powerdns.com.")) {
5820 addRRSIG(keys
, res
->d_records
, domain
, 300);
5822 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5823 if (domain
== DNSName("powerdns.com.")) {
5824 addRRSIG(keys
, res
->d_records
, domain
, 300);
5828 if (domain
== target
) {
5829 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
5831 else if (domain
== targetCName
) {
5832 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
5833 addRRSIG(keys
, res
->d_records
, domain
, 300);
5843 vector
<DNSRecord
> ret
;
5844 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5845 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5846 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5847 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5848 BOOST_CHECK_EQUAL(queriesCount
, 11);
5850 /* again, to test the cache */
5852 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5853 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5854 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5855 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5856 BOOST_CHECK_EQUAL(queriesCount
, 11);
5859 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname
) {
5860 std::unique_ptr
<SyncRes
> sr
;
5863 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5866 const DNSName
target("power-dns.com.");
5867 const DNSName
targetCName("powerdns.com.");
5868 const ComboAddress
targetCNameAddr("192.0.2.42");
5871 auto luaconfsCopy
= g_luaconfs
.getCopy();
5872 luaconfsCopy
.dsAnchors
.clear();
5873 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5874 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5875 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5876 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5877 g_luaconfs
.setState(luaconfsCopy
);
5879 size_t queriesCount
= 0;
5881 sr
->setAsyncCallback([target
,targetCName
,targetCNameAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5884 if (type
== QType::DS
) {
5887 else if (type
== QType::DNSKEY
) {
5888 setLWResult(res
, 0, true, false, true);
5889 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5890 addRRSIG(keys
, res
->d_records
, domain
, 300);
5894 if (isRootServer(ip
)) {
5895 setLWResult(res
, 0, false, false, true);
5896 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5897 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5898 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5899 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5902 else if (ip
== ComboAddress("192.0.2.1:53")) {
5903 if (domain
== DNSName("com.")) {
5904 setLWResult(res
, 0, true, false, true);
5905 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5906 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5907 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5908 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5910 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
5911 setLWResult(res
, 0, false, false, true);
5912 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5913 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
5914 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5915 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5919 else if (ip
== ComboAddress("192.0.2.2:53")) {
5920 setLWResult(res
, 0, true, false, true);
5921 if (type
== QType::NS
) {
5922 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5923 addRRSIG(keys
, res
->d_records
, domain
, 300);
5924 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5925 addRRSIG(keys
, res
->d_records
, domain
, 300);
5928 if (domain
== target
) {
5929 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
5930 /* No RRSIG, leading to bogus */
5932 else if (domain
== targetCName
) {
5933 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
5934 addRRSIG(keys
, res
->d_records
, domain
, 300);
5944 vector
<DNSRecord
> ret
;
5945 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5946 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5947 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5948 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5949 BOOST_CHECK_EQUAL(queriesCount
, 11);
5951 /* again, to test the cache */
5953 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5954 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5955 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5956 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5957 BOOST_CHECK_EQUAL(queriesCount
, 11);
5960 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname
) {
5961 std::unique_ptr
<SyncRes
> sr
;
5964 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5967 const DNSName
target("power-dns.com.");
5968 const DNSName
targetCName("powerdns.com.");
5969 const ComboAddress
targetCNameAddr("192.0.2.42");
5972 auto luaconfsCopy
= g_luaconfs
.getCopy();
5973 luaconfsCopy
.dsAnchors
.clear();
5974 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5975 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5976 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5977 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5978 g_luaconfs
.setState(luaconfsCopy
);
5980 size_t queriesCount
= 0;
5982 sr
->setAsyncCallback([target
,targetCName
,targetCNameAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
5985 if (type
== QType::DS
) {
5988 else if (type
== QType::DNSKEY
) {
5989 setLWResult(res
, 0, true, false, true);
5990 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5991 addRRSIG(keys
, res
->d_records
, domain
, 300);
5995 if (isRootServer(ip
)) {
5996 setLWResult(res
, 0, false, false, true);
5997 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5998 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5999 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6000 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6003 else if (ip
== ComboAddress("192.0.2.1:53")) {
6004 if (domain
== DNSName("com.")) {
6005 setLWResult(res
, 0, true, false, true);
6006 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6007 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6008 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6009 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6011 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
6012 setLWResult(res
, 0, false, false, true);
6013 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6014 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
6015 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6016 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6020 else if (ip
== ComboAddress("192.0.2.2:53")) {
6021 setLWResult(res
, 0, true, false, true);
6022 if (type
== QType::NS
) {
6023 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6024 addRRSIG(keys
, res
->d_records
, domain
, 300);
6025 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6026 addRRSIG(keys
, res
->d_records
, domain
, 300);
6029 if (domain
== target
) {
6030 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6031 addRRSIG(keys
, res
->d_records
, domain
, 300);
6033 else if (domain
== targetCName
) {
6034 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6035 /* No RRSIG, leading to bogus */
6045 vector
<DNSRecord
> ret
;
6046 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6047 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6048 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6049 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6050 BOOST_CHECK_EQUAL(queriesCount
, 11);
6052 /* again, to test the cache */
6054 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6055 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6056 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6057 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6058 BOOST_CHECK_EQUAL(queriesCount
, 11);
6061 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname
) {
6062 std::unique_ptr
<SyncRes
> sr
;
6065 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6068 const DNSName
target("power-dns.com.");
6069 const DNSName
targetCName("powerdns.com.");
6070 const ComboAddress
targetCNameAddr("192.0.2.42");
6073 auto luaconfsCopy
= g_luaconfs
.getCopy();
6074 luaconfsCopy
.dsAnchors
.clear();
6075 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6076 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6077 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6078 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6079 g_luaconfs
.setState(luaconfsCopy
);
6081 size_t queriesCount
= 0;
6083 sr
->setAsyncCallback([target
,targetCName
,targetCNameAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
6086 if (type
== QType::DS
) {
6089 else if (type
== QType::DNSKEY
) {
6090 setLWResult(res
, 0, true, false, true);
6091 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6092 addRRSIG(keys
, res
->d_records
, domain
, 300);
6096 if (isRootServer(ip
)) {
6097 setLWResult(res
, 0, false, false, true);
6098 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6099 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6100 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6101 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6104 else if (ip
== ComboAddress("192.0.2.1:53")) {
6105 if (domain
== DNSName("com.")) {
6106 setLWResult(res
, 0, true, false, true);
6107 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6108 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6109 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6110 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6112 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
6113 setLWResult(res
, 0, false, false, true);
6114 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6115 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
6116 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6117 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6121 else if (ip
== ComboAddress("192.0.2.2:53")) {
6122 setLWResult(res
, 0, true, false, true);
6123 if (type
== QType::NS
) {
6124 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6125 addRRSIG(keys
, res
->d_records
, domain
, 300);
6126 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6127 addRRSIG(keys
, res
->d_records
, domain
, 300);
6130 if (domain
== target
) {
6131 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6132 addRRSIG(keys
, res
->d_records
, domain
, 300);
6134 else if (domain
== targetCName
) {
6135 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6136 addRRSIG(keys
, res
->d_records
, domain
, 300);
6146 vector
<DNSRecord
> ret
;
6147 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6148 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6149 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6150 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6151 BOOST_CHECK_EQUAL(queriesCount
, 12);
6153 /* again, to test the cache */
6155 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6156 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6157 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6158 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6159 BOOST_CHECK_EQUAL(queriesCount
, 12);
6162 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname
) {
6163 std::unique_ptr
<SyncRes
> sr
;
6166 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6169 const DNSName
target("powerdns.com.");
6170 const DNSName
targetCName("power-dns.com.");
6171 const ComboAddress
targetCNameAddr("192.0.2.42");
6174 auto luaconfsCopy
= g_luaconfs
.getCopy();
6175 luaconfsCopy
.dsAnchors
.clear();
6176 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6177 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6178 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6179 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6180 g_luaconfs
.setState(luaconfsCopy
);
6182 size_t queriesCount
= 0;
6184 sr
->setAsyncCallback([target
,targetCName
,targetCNameAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
6187 if (type
== QType::DS
) {
6188 if (domain
== DNSName("power-dns.com.")) {
6189 setLWResult(res
, 0, false, false, true);
6190 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6191 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6192 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6196 else if (type
== QType::DNSKEY
) {
6197 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6198 setLWResult(res
, 0, true, false, true);
6199 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6200 addRRSIG(keys
, res
->d_records
, domain
, 300);
6204 setLWResult(res
, 0, false, false, true);
6205 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6210 if (isRootServer(ip
)) {
6211 setLWResult(res
, 0, false, false, true);
6212 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6213 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6214 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6215 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6218 else if (ip
== ComboAddress("192.0.2.1:53")) {
6219 if (domain
== DNSName("com.")) {
6220 setLWResult(res
, 0, true, false, true);
6221 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6222 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6223 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6224 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6226 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
6227 setLWResult(res
, 0, false, false, true);
6228 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6229 if (domain
== DNSName("powerdns.com.")) {
6230 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6232 else if (domain
== targetCName
) {
6233 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6235 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6236 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6240 else if (ip
== ComboAddress("192.0.2.2:53")) {
6241 setLWResult(res
, 0, true, false, true);
6242 if (type
== QType::NS
) {
6243 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6244 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6247 if (domain
== DNSName("powerdns.com.")) {
6248 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6249 /* No RRSIG -> Bogus */
6251 else if (domain
== targetCName
) {
6252 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6262 vector
<DNSRecord
> ret
;
6263 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6264 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6265 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6266 /* no RRSIG to show */
6267 BOOST_CHECK_EQUAL(ret
.size(), 2);
6268 BOOST_CHECK_EQUAL(queriesCount
, 10);
6270 /* again, to test the cache */
6272 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6273 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6274 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6275 BOOST_CHECK_EQUAL(ret
.size(), 2);
6276 BOOST_CHECK_EQUAL(queriesCount
, 10);
6279 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta
) {
6280 std::unique_ptr
<SyncRes
> sr
;
6283 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6286 const DNSName
target("powerdns.com.");
6287 const ComboAddress
targetAddr("192.0.2.42");
6290 auto luaconfsCopy
= g_luaconfs
.getCopy();
6291 luaconfsCopy
.dsAnchors
.clear();
6292 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6293 /* No key material for .com */
6294 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6295 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
6296 g_luaconfs
.setState(luaconfsCopy
);
6298 size_t queriesCount
= 0;
6300 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
6303 if (type
== QType::DNSKEY
) {
6304 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
6305 setLWResult(res
, 0, true, false, true);
6306 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6307 addRRSIG(keys
, res
->d_records
, domain
, 300);
6310 else if (domain
== DNSName("com.")) {
6311 setLWResult(res
, 0, false, false, true);
6312 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6317 if (isRootServer(ip
)) {
6318 setLWResult(res
, 0, false, false, true);
6319 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6320 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
6321 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6322 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6325 else if (ip
== ComboAddress("192.0.2.1:53")) {
6326 if (target
== domain
) {
6327 setLWResult(res
, 0, false, false, true);
6328 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6329 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6331 else if (domain
== DNSName("com.")) {
6332 setLWResult(res
, 0, true, false, true);
6333 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6334 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6338 else if (ip
== ComboAddress("192.0.2.2:53")) {
6339 setLWResult(res
, 0, true, false, true);
6340 if (type
== QType::NS
) {
6341 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6344 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6346 addRRSIG(keys
, res
->d_records
, domain
, 300);
6354 vector
<DNSRecord
> ret
;
6355 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6356 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6357 /* should be insecure but we have a TA for powerdns.com. */
6358 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6359 /* We got a RRSIG */
6360 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6361 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6362 /* - NS com. (at . and com.)
6363 - NS powerdns.com (com. and powerdns.com.)
6364 - DNSKEY (. and powerdns.com.)
6367 BOOST_CHECK_EQUAL(queriesCount
, 7);
6369 /* again, to test the cache */
6371 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6372 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6373 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6374 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6375 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6376 BOOST_CHECK_EQUAL(queriesCount
, 7);
6379 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig
) {
6380 std::unique_ptr
<SyncRes
> sr
;
6383 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6386 const DNSName
target("powerdns.com.");
6387 const ComboAddress
targetAddr("192.0.2.42");
6390 auto luaconfsCopy
= g_luaconfs
.getCopy();
6391 luaconfsCopy
.dsAnchors
.clear();
6392 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6393 /* No key material for .com */
6394 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6395 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
6396 g_luaconfs
.setState(luaconfsCopy
);
6398 size_t queriesCount
= 0;
6400 sr
->setAsyncCallback([target
,targetAddr
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
6403 if (type
== QType::DNSKEY
) {
6404 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
6405 setLWResult(res
, 0, true, false, true);
6406 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6407 addRRSIG(keys
, res
->d_records
, domain
, 300);
6410 else if (domain
== DNSName("com.")) {
6411 setLWResult(res
, 0, false, false, true);
6412 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6417 if (target
.isPartOf(domain
) && isRootServer(ip
)) {
6418 setLWResult(res
, 0, false, false, true);
6419 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6420 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
6421 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6422 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6425 else if (ip
== ComboAddress("192.0.2.1:53")) {
6426 if (target
== domain
) {
6427 setLWResult(res
, 0, false, false, true);
6428 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6429 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6431 else if (domain
== DNSName("com.")) {
6432 setLWResult(res
, 0, true, false, true);
6433 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6434 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6438 else if (domain
== target
&& ip
== ComboAddress("192.0.2.2:53")) {
6439 setLWResult(res
, 0, true, false, true);
6440 if (type
== QType::NS
) {
6441 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6444 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6446 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
6454 vector
<DNSRecord
> ret
;
6455 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6456 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6457 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
6458 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6460 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6461 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6462 /* - NS com. (at . and com.)
6463 - NS powerdns.com (com. and powerdns.com.)
6465 - A powerdns.com (no DNSKEY because no RRSIG)
6467 BOOST_CHECK_EQUAL(queriesCount
, 6);
6469 /* again, to test the cache */
6471 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6472 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6473 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6474 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6475 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6476 BOOST_CHECK_EQUAL(queriesCount
, 6);
6479 BOOST_AUTO_TEST_CASE(test_dnssec_nta
) {
6480 std::unique_ptr
<SyncRes
> sr
;
6483 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6486 const DNSName
target(".");
6489 auto luaconfsCopy
= g_luaconfs
.getCopy();
6490 luaconfsCopy
.dsAnchors
.clear();
6491 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6492 /* Add a NTA for "." */
6493 luaconfsCopy
.negAnchors
[g_rootdnsname
] = "NTA for Root";
6494 g_luaconfs
.setState(luaconfsCopy
);
6496 size_t queriesCount
= 0;
6498 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
6501 if (domain
== target
&& type
== QType::NS
) {
6503 setLWResult(res
, 0, true, false, true);
6504 char addr
[] = "a.root-servers.net.";
6505 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
6507 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
6510 addRRSIG(keys
, res
->d_records
, domain
, 300);
6512 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
6513 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
6516 } else if (domain
== target
&& type
== QType::DNSKEY
) {
6518 setLWResult(res
, 0, true, false, true);
6528 vector
<DNSRecord
> ret
;
6529 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
6530 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6531 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6532 /* 13 NS + 1 RRSIG */
6533 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
6534 BOOST_CHECK_EQUAL(queriesCount
, 1);
6536 /* again, to test the cache */
6538 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
6539 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6540 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6541 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
6542 BOOST_CHECK_EQUAL(queriesCount
, 1);
6545 BOOST_AUTO_TEST_CASE(test_dnssec_no_ta
) {
6546 std::unique_ptr
<SyncRes
> sr
;
6549 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6552 const DNSName
target(".");
6555 /* Remove the root DS */
6556 auto luaconfsCopy
= g_luaconfs
.getCopy();
6557 luaconfsCopy
.dsAnchors
.clear();
6558 g_luaconfs
.setState(luaconfsCopy
);
6560 size_t queriesCount
= 0;
6562 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
6565 if (domain
== target
&& type
== QType::NS
) {
6567 setLWResult(res
, 0, true, false, true);
6568 char addr
[] = "a.root-servers.net.";
6569 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
6571 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
6574 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
6575 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
6583 vector
<DNSRecord
> ret
;
6584 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
6585 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6586 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6587 /* 13 NS + 0 RRSIG */
6588 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
6589 BOOST_CHECK_EQUAL(queriesCount
, 1);
6591 /* again, to test the cache */
6593 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
6594 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6595 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6596 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
6597 BOOST_CHECK_EQUAL(queriesCount
, 1);
6600 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata
) {
6601 std::unique_ptr
<SyncRes
> sr
;
6604 g_dnssecmode
= DNSSECMode::ValidateAll
;
6607 const DNSName
target("powerdns.com.");
6610 auto luaconfsCopy
= g_luaconfs
.getCopy();
6611 luaconfsCopy
.dsAnchors
.clear();
6612 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6613 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6614 g_luaconfs
.setState(luaconfsCopy
);
6616 size_t queriesCount
= 0;
6618 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
) {
6621 if (type
== QType::DS
) {
6624 else if (type
== QType::DNSKEY
) {
6625 setLWResult(res
, 0, true, false, true);
6626 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6627 addRRSIG(keys
, res
->d_records
, domain
, 300);
6632 setLWResult(res
, 0, true, false, true);
6639 vector
<DNSRecord
> ret
;
6640 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6641 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6642 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6643 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
6644 /* com|NS, powerdns.com|NS, powerdns.com|A */
6645 BOOST_CHECK_EQUAL(queriesCount
, 3);
6647 /* again, to test the cache */
6649 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6650 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6651 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6652 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
6653 /* we don't store empty results */
6654 BOOST_CHECK_EQUAL(queriesCount
, 6);
6658 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
6660 - check out of band support
6666 BOOST_AUTO_TEST_SUITE_END()