1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3 #include <boost/test/unit_test.hpp>
5 #include "arguments.hh"
7 #include "dnssecinfra.hh"
8 #include "dnsseckeeper.hh"
9 #include "lua-recursor4.hh"
10 #include "namespaces.hh"
11 #include "rec-lua-conf.hh"
12 #include "root-dnssec.hh"
14 #include "test-common.hh"
16 #include "validate-recursor.hh"
18 RecursorStats g_stats
;
19 GlobalStateHolder
<LuaConfigItems
> g_luaconfs
;
20 thread_local
std::unique_ptr
<MemRecursorCache
> t_RC
{nullptr};
21 unsigned int g_numThreads
= 1;
22 bool g_lowercaseOutgoing
= false;
24 /* Fake some required functions we didn't want the trouble to
28 static ArgvMap theArg
;
37 bool RecursorLua4::preoutquery(const ComboAddress
& ns
, const ComboAddress
& requestor
, const DNSName
& query
, const QType
& qtype
, bool isTcp
, vector
<DNSRecord
>& res
, int& ret
)
42 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
)
47 /* primeHints() is only here for now because it
48 was way too much trouble to link with the real one.
49 We should fix this, empty functions are one thing, but this is
53 #include "root-addresses.hh"
57 vector
<DNSRecord
> nsset
;
59 t_RC
= std::unique_ptr
<MemRecursorCache
>(new MemRecursorCache());
61 DNSRecord arr
, aaaarr
, nsrr
;
62 nsrr
.d_name
=g_rootdnsname
;
64 aaaarr
.d_type
=QType::AAAA
;
65 nsrr
.d_type
=QType::NS
;
66 arr
.d_ttl
=aaaarr
.d_ttl
=nsrr
.d_ttl
=time(nullptr)+3600000;
68 for(char c
='a';c
<='m';++c
) {
69 static char templ
[40];
70 strncpy(templ
,"a.root-servers.net.", sizeof(templ
) - 1);
71 templ
[sizeof(templ
)-1] = '\0';
73 aaaarr
.d_name
=arr
.d_name
=DNSName(templ
);
74 nsrr
.d_content
=std::make_shared
<NSRecordContent
>(DNSName(templ
));
75 arr
.d_content
=std::make_shared
<ARecordContent
>(ComboAddress(rootIps4
[c
-'a']));
76 vector
<DNSRecord
> aset
;
78 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
79 if (rootIps6
[c
-'a'] != NULL
) {
80 aaaarr
.d_content
=std::make_shared
<AAAARecordContent
>(ComboAddress(rootIps6
[c
-'a']));
82 vector
<DNSRecord
> aaaaset
;
83 aaaaset
.push_back(aaaarr
);
84 t_RC
->replace(time(0), DNSName(templ
), QType(QType::AAAA
), aaaaset
, vector
<std::shared_ptr
<RRSIGRecordContent
>>(), vector
<std::shared_ptr
<DNSRecord
>>(), true);
87 nsset
.push_back(nsrr
);
89 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
92 LuaConfigItems::LuaConfigItems()
94 for (const auto &dsRecord
: rootDSs
) {
95 auto ds
=unique_ptr
<DSRecordContent
>(dynamic_cast<DSRecordContent
*>(DSRecordContent::make(dsRecord
)));
96 dsAnchors
[g_rootdnsname
].insert(*ds
);
100 /* Some helpers functions */
102 static void init(bool debug
=false)
106 L
.setLoglevel((Logger::Urgency
)(6)); // info and up
107 L
.disableSyslog(true);
108 L
.toConsole(Logger::Info
);
111 seedRandom("/dev/urandom");
114 t_RC
= std::unique_ptr
<MemRecursorCache
>(new MemRecursorCache());
116 SyncRes::s_maxqperq
= 50;
117 SyncRes::s_maxtotusec
= 1000*7000;
118 SyncRes::s_maxdepth
= 40;
119 SyncRes::s_maxnegttl
= 3600;
120 SyncRes::s_maxcachettl
= 86400;
121 SyncRes::s_packetcachettl
= 3600;
122 SyncRes::s_packetcacheservfailttl
= 60;
123 SyncRes::s_serverdownmaxfails
= 64;
124 SyncRes::s_serverdownthrottletime
= 60;
125 SyncRes::s_doIPv6
= true;
126 SyncRes::s_ecsipv4limit
= 24;
127 SyncRes::s_ecsipv6limit
= 56;
128 SyncRes::s_rootNXTrust
= true;
129 SyncRes::s_minimumTTL
= 0;
130 SyncRes::s_serverID
= "PowerDNS Unit Tests Server ID";
131 SyncRes::clearEDNSSubnets();
132 SyncRes::clearEDNSDomains();
133 SyncRes::clearDelegationOnly();
134 SyncRes::clearDontQuery();
136 SyncRes::clearNSSpeeds();
137 BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0);
138 SyncRes::clearEDNSStatuses();
139 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0);
140 SyncRes::clearThrottle();
141 BOOST_CHECK_EQUAL(SyncRes::getThrottledServersSize(), 0);
142 SyncRes::clearFailedServers();
143 BOOST_CHECK_EQUAL(SyncRes::getFailedServersSize(), 0);
145 auto luaconfsCopy
= g_luaconfs
.getCopy();
146 luaconfsCopy
.dfe
.clear();
147 luaconfsCopy
.dsAnchors
.clear();
148 for (const auto &dsRecord
: rootDSs
) {
149 auto ds
=unique_ptr
<DSRecordContent
>(dynamic_cast<DSRecordContent
*>(DSRecordContent::make(dsRecord
)));
150 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(*ds
);
152 luaconfsCopy
.negAnchors
.clear();
153 g_luaconfs
.setState(luaconfsCopy
);
155 g_dnssecmode
= DNSSECMode::Off
;
157 g_maxNSEC3Iterations
= 2500;
159 ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Unit Tests";
162 static void initSR(std::unique_ptr
<SyncRes
>& sr
, bool dnssec
=false, bool debug
=false, time_t fakeNow
=0)
166 now
.tv_sec
= fakeNow
;
170 Utility::gettimeofday(&now
, 0);
175 sr
= std::unique_ptr
<SyncRes
>(new SyncRes(now
));
176 sr
->setDoEDNS0(true);
178 sr
->setDoDNSSEC(dnssec
);
181 sr
->setLogMode(debug
== false ? SyncRes::LogNone
: SyncRes::Log
);
183 SyncRes::setDomainMap(std::make_shared
<SyncRes::domainmap_t
>());
184 SyncRes::clearNegCache();
187 static void setDNSSECValidation(std::unique_ptr
<SyncRes
>& sr
, const DNSSECMode
& mode
)
189 sr
->setDNSSECValidationRequested(true);
193 static void setLWResult(LWResult
* res
, int rcode
, bool aa
=false, bool tc
=false, bool edns
=false)
195 res
->d_rcode
= rcode
;
198 res
->d_haveEDNS
= edns
;
201 static void addRecordToLW(LWResult
* res
, const DNSName
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
=DNSResourceRecord::ANSWER
, uint32_t ttl
=60)
203 addRecordToList(res
->d_records
, name
, type
, content
, place
, ttl
);
206 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)
208 addRecordToLW(res
, DNSName(name
), type
, content
, place
, ttl
);
211 static bool isRootServer(const ComboAddress
& ip
)
214 for (size_t idx
= 0; idx
< rootIps4Count
; idx
++) {
215 if (ip
.toString() == rootIps4
[idx
]) {
221 for (size_t idx
= 0; idx
< rootIps6Count
; idx
++) {
222 if (ip
.toString() == rootIps6
[idx
]) {
231 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
)
233 time_t now
= time(nullptr);
234 DNSKEYRecordContent drc
= dpk
.getDNSKEY();
235 const std::shared_ptr
<DNSCryptoKeyEngine
> rc
= dpk
.getKey();
237 rrc
.d_type
= signQType
;
238 rrc
.d_labels
= signQName
.countLabels() - signQName
.isWildcard();
239 rrc
.d_originalttl
= signTTL
;
240 rrc
.d_siginception
= inception
? *inception
: (now
- 10);
241 rrc
.d_sigexpire
= now
+ sigValidity
;
242 rrc
.d_signer
= signer
;
244 rrc
.d_tag
= drc
.getTag();
245 rrc
.d_algorithm
= algo
? *algo
: drc
.d_algorithm
;
247 std::string msg
= getMessageForRRSET(signQName
, rrc
, toSign
);
249 rrc
.d_signature
= rc
->sign(msg
);
252 typedef std::unordered_map
<DNSName
, std::pair
<DNSSECPrivateKey
, DSRecordContent
> > testkeysset_t
;
254 static bool 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
)
256 if (records
.empty()) {
260 const auto it
= keys
.find(signer
);
261 if (it
== keys
.cend()) {
262 throw std::runtime_error("No DNSKEY found for " + signer
.toString() + ", unable to compute the requested RRSIG");
265 size_t recordsCount
= records
.size();
266 const DNSName
& name
= records
[recordsCount
-1].d_name
;
267 const uint16_t type
= records
[recordsCount
-1].d_type
;
269 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
270 for (const auto record
: records
) {
271 if (record
.d_name
== name
&& record
.d_type
== type
) {
272 recordcontents
.push_back(record
.d_content
);
276 RRSIGRecordContent rrc
;
277 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
);
279 rrc
.d_signature
[0] ^= 42;
283 rec
.d_type
= QType::RRSIG
;
284 rec
.d_place
= records
[recordsCount
-1].d_place
;
285 rec
.d_name
= records
[recordsCount
-1].d_name
;
286 rec
.d_ttl
= records
[recordsCount
-1].d_ttl
;
288 rec
.d_content
= std::make_shared
<RRSIGRecordContent
>(rrc
);
289 records
.push_back(rec
);
294 static void addDNSKEY(const testkeysset_t
& keys
, const DNSName
& signer
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
296 const auto it
= keys
.find(signer
);
297 if (it
== keys
.cend()) {
298 throw std::runtime_error("No DNSKEY found for " + signer
.toString());
302 rec
.d_place
= DNSResourceRecord::ANSWER
;
304 rec
.d_type
= QType::DNSKEY
;
307 rec
.d_content
= std::make_shared
<DNSKEYRecordContent
>(it
->second
.first
.getDNSKEY());
308 records
.push_back(rec
);
311 static bool addDS(const DNSName
& domain
, uint32_t ttl
, std::vector
<DNSRecord
>& records
, const testkeysset_t
& keys
, DNSResourceRecord::Place place
=DNSResourceRecord::AUTHORITY
)
313 const auto it
= keys
.find(domain
);
314 if (it
== keys
.cend()) {
320 rec
.d_type
= QType::DS
;
323 rec
.d_content
= std::make_shared
<DSRecordContent
>(it
->second
.second
);
325 records
.push_back(rec
);
329 static void addNSECRecordToLW(const DNSName
& domain
, const DNSName
& next
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
331 NSECRecordContent nrc
;
338 rec
.d_type
= QType::NSEC
;
339 rec
.d_content
= std::make_shared
<NSECRecordContent
>(nrc
);
340 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
342 records
.push_back(rec
);
345 static void addNSEC3RecordToLW(const DNSName
& hashedName
, const std::string
& hashedNext
, const std::string
& salt
, unsigned int iterations
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
347 NSEC3RecordContent nrc
;
350 nrc
.d_iterations
= iterations
;
352 nrc
.d_nexthash
= hashedNext
;
356 rec
.d_name
= hashedName
;
358 rec
.d_type
= QType::NSEC3
;
359 rec
.d_content
= std::make_shared
<NSEC3RecordContent
>(nrc
);
360 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
362 records
.push_back(rec
);
365 static void addNSEC3UnhashedRecordToLW(const DNSName
& domain
, const DNSName
& zone
, const std::string
& next
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
, unsigned int iterations
=10)
367 static const std::string salt
= "deadbeef";
368 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
370 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, next
, salt
, iterations
, types
, ttl
, records
);
373 static void addNSEC3NarrowRecordToLW(const DNSName
& domain
, const DNSName
& zone
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
, unsigned int iterations
=10)
375 static const std::string salt
= "deadbeef";
376 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
377 std::string
hashedNext(hashed
);
378 incrementHash(hashedNext
);
379 decrementHash(hashed
);
381 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, hashedNext
, salt
, iterations
, types
, ttl
, records
);
384 static void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
)
386 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(algo
));
387 dcke
->create((algo
<= 10) ? 2048 : dcke
->getBits());
388 DNSSECPrivateKey dpk
;
391 DSRecordContent ds
= makeDSFromDNSKey(name
, dpk
.getDNSKEY(), digest
);
392 keys
[name
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
,ds
);
395 static void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
, map
<DNSName
,dsmap_t
>& dsAnchors
)
397 generateKeyMaterial(name
, algo
, digest
, keys
);
398 dsAnchors
[name
].insert(keys
[name
].second
);
401 static int genericDSAndDNSKEYHandler(LWResult
* res
, const DNSName
& domain
, DNSName auth
, int type
, const testkeysset_t
& keys
, bool proveCut
=true)
403 if (type
== QType::DS
) {
406 setLWResult(res
, 0, true, false, true);
408 if (addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
)) {
409 addRRSIG(keys
, res
->d_records
, auth
, 300);
412 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
414 /* if the auth zone is signed, we need to provide a secure denial */
415 const auto it
= keys
.find(auth
);
416 if (it
!= keys
.cend()) {
418 addRRSIG(keys
, res
->d_records
, auth
, 300);
419 /* add a NSEC denying the DS */
420 std::set
<uint16_t> types
= { QType::NSEC
};
422 types
.insert(QType::NS
);
425 addNSECRecordToLW(domain
, DNSName("z") + domain
, types
, 600, res
->d_records
);
426 addRRSIG(keys
, res
->d_records
, auth
, 300);
433 if (type
== QType::DNSKEY
) {
434 setLWResult(res
, 0, true, false, true);
435 addDNSKEY(keys
, domain
, 300, res
->d_records
);
436 addRRSIG(keys
, res
->d_records
, domain
, 300);
445 BOOST_AUTO_TEST_SUITE(syncres_cc
)
447 BOOST_AUTO_TEST_CASE(test_root_primed
) {
448 std::unique_ptr
<SyncRes
> sr
;
453 const DNSName
target("a.root-servers.net.");
455 /* we are primed, we should be able to resolve A a.root-servers.net. without any query */
456 vector
<DNSRecord
> ret
;
457 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
458 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
459 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
460 BOOST_CHECK(ret
[0].d_type
== QType::A
);
461 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
464 res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
465 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
466 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
467 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
468 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
469 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
472 BOOST_AUTO_TEST_CASE(test_root_primed_ns
) {
473 std::unique_ptr
<SyncRes
> sr
;
477 const DNSName
target(".");
479 /* we are primed, but we should not be able to NS . without any query
480 because the . NS entry is not stored as authoritative */
482 size_t queriesCount
= 0;
484 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
) {
487 if (domain
== target
&& type
== QType::NS
) {
489 setLWResult(res
, 0, true, false, true);
490 char addr
[] = "a.root-servers.net.";
491 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
493 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
496 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
497 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
505 vector
<DNSRecord
> ret
;
506 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
507 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
508 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
509 BOOST_CHECK_EQUAL(queriesCount
, 1);
512 BOOST_AUTO_TEST_CASE(test_root_not_primed
) {
513 std::unique_ptr
<SyncRes
> sr
;
516 size_t queriesCount
= 0;
518 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
) {
521 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
522 setLWResult(res
, 0, true, false, true);
523 addRecordToLW(res
, g_rootdnsname
, QType::NS
, "a.root-servers.net.", DNSResourceRecord::ANSWER
, 3600);
524 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
525 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
533 /* we are not primed yet, so SyncRes will have to call primeHints()
534 then call getRootNS(), for which at least one of the root servers needs to answer */
535 vector
<DNSRecord
> ret
;
536 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
537 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
538 BOOST_CHECK_EQUAL(ret
.size(), 1);
539 BOOST_CHECK_EQUAL(queriesCount
, 2);
542 BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response
) {
543 std::unique_ptr
<SyncRes
> sr
;
545 std::set
<ComboAddress
> downServers
;
547 /* we are not primed yet, so SyncRes will have to call primeHints()
548 then call getRootNS(), for which at least one of the root servers needs to answer.
549 None will, so it should ServFail.
551 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
) {
553 downServers
.insert(ip
);
557 vector
<DNSRecord
> ret
;
558 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
559 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
560 BOOST_CHECK_EQUAL(ret
.size(), 0);
561 BOOST_CHECK(downServers
.size() > 0);
562 /* we explicitly refuse to mark the root servers down */
563 for (const auto& server
: downServers
) {
564 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
568 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback
) {
569 std::unique_ptr
<SyncRes
> sr
;
572 ComboAddress noEDNSServer
;
573 size_t queriesWithEDNS
= 0;
574 size_t queriesWithoutEDNS
= 0;
576 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
) {
577 if (EDNS0Level
!= 0) {
581 setLWResult(res
, RCode::FormErr
);
585 queriesWithoutEDNS
++;
587 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
588 setLWResult(res
, 0, true, false, false);
589 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
598 /* fake that the root NS doesn't handle EDNS, check that we fallback */
599 vector
<DNSRecord
> ret
;
600 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
601 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
602 BOOST_CHECK_EQUAL(ret
.size(), 1);
603 BOOST_CHECK_EQUAL(queriesWithEDNS
, 1);
604 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 1);
605 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 1);
606 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer
), SyncRes::EDNSStatus::NOEDNS
);
609 BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback
) {
610 std::unique_ptr
<SyncRes
> sr
;
613 size_t queriesWithEDNS
= 0;
614 size_t queriesWithoutEDNS
= 0;
616 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
) {
617 if (EDNS0Level
!= 0) {
619 setLWResult(res
, RCode::NotImp
);
623 queriesWithoutEDNS
++;
625 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
626 setLWResult(res
, 0, true, false, false);
627 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
636 /* fake that the NS doesn't handle EDNS, check that we fallback */
637 vector
<DNSRecord
> ret
;
638 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
639 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
640 BOOST_CHECK_EQUAL(ret
.size(), 1);
641 BOOST_CHECK_EQUAL(queriesWithEDNS
, 1);
642 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 1);
645 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
) {
646 std::unique_ptr
<SyncRes
> sr
;
649 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
) {
651 setLWResult(res
, 0, false, true, false);
654 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
655 setLWResult(res
, 0, true, false, false);
656 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
665 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
666 vector
<DNSRecord
> ret
;
667 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
668 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
671 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
) {
672 std::unique_ptr
<SyncRes
> sr
;
675 size_t tcpQueriesCount
= 0;
677 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
) {
679 setLWResult(res
, 0, true, true, false);
683 /* first TCP query is answered with a TC response */
685 if (tcpQueriesCount
== 1) {
686 setLWResult(res
, 0, true, true, false);
689 setLWResult(res
, 0, true, false, false);
692 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
698 vector
<DNSRecord
> ret
;
699 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
700 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
701 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2);
704 BOOST_AUTO_TEST_CASE(test_all_nss_down
) {
705 std::unique_ptr
<SyncRes
> sr
;
707 std::set
<ComboAddress
> downServers
;
711 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
) {
713 if (isRootServer(ip
)) {
714 setLWResult(res
, 0, false, false, true);
715 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
716 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
717 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
720 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
721 setLWResult(res
, 0, false, false, true);
722 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
723 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
724 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
725 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
726 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
727 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
731 downServers
.insert(ip
);
736 DNSName
target("powerdns.com.");
738 vector
<DNSRecord
> ret
;
739 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
740 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
741 BOOST_CHECK_EQUAL(ret
.size(), 0);
742 BOOST_CHECK_EQUAL(downServers
.size(), 4);
744 for (const auto& server
: downServers
) {
745 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
746 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
750 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
) {
751 std::unique_ptr
<SyncRes
> sr
;
753 std::set
<ComboAddress
> downServers
;
757 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
) {
759 if (isRootServer(ip
)) {
760 setLWResult(res
, 0, false, false, true);
761 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
762 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
763 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
766 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
767 setLWResult(res
, 0, false, false, true);
768 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
769 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
770 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
771 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
772 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
773 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
777 downServers
.insert(ip
);
782 /* exact same test than the previous one, except instead of a time out we fake a network error */
783 DNSName
target("powerdns.com.");
785 vector
<DNSRecord
> ret
;
786 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
787 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
788 BOOST_CHECK_EQUAL(ret
.size(), 0);
789 BOOST_CHECK_EQUAL(downServers
.size(), 4);
791 for (const auto& server
: downServers
) {
792 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
793 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
798 BOOST_AUTO_TEST_CASE(test_os_limit_errors
) {
799 std::unique_ptr
<SyncRes
> sr
;
801 std::set
<ComboAddress
> downServers
;
805 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
) {
807 if (isRootServer(ip
)) {
808 setLWResult(res
, 0, false, false, true);
809 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
810 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
811 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
814 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
815 setLWResult(res
, 0, false, false, true);
816 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
817 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
818 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
819 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
820 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
821 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
825 if (downServers
.size() < 3) {
826 /* only the last one will answer */
827 downServers
.insert(ip
);
831 setLWResult(res
, 0, true, false, true);
832 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
838 DNSName
target("powerdns.com.");
840 vector
<DNSRecord
> ret
;
841 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
842 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
843 BOOST_CHECK_EQUAL(ret
.size(), 1);
844 BOOST_CHECK_EQUAL(downServers
.size(), 3);
846 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
847 for (const auto& server
: downServers
) {
848 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
849 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
853 BOOST_AUTO_TEST_CASE(test_glued_referral
) {
854 std::unique_ptr
<SyncRes
> sr
;
859 const DNSName
target("powerdns.com.");
861 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
) {
862 /* this will cause issue with qname minimization if we ever implement it */
863 if (domain
!= target
) {
867 if (isRootServer(ip
)) {
868 setLWResult(res
, 0, false, false, true);
869 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
870 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
871 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
874 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
875 setLWResult(res
, 0, false, false, true);
876 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
877 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
878 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
879 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
880 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
881 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
884 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")) {
885 setLWResult(res
, 0, true, false, true);
886 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
894 vector
<DNSRecord
> ret
;
895 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
896 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
897 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
898 BOOST_CHECK(ret
[0].d_type
== QType::A
);
899 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
902 BOOST_AUTO_TEST_CASE(test_glueless_referral
) {
903 std::unique_ptr
<SyncRes
> sr
;
908 const DNSName
target("powerdns.com.");
910 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
) {
912 if (isRootServer(ip
)) {
913 setLWResult(res
, 0, false, false, true);
915 if (domain
.isPartOf(DNSName("com."))) {
916 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
917 } else if (domain
.isPartOf(DNSName("org."))) {
918 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
921 setLWResult(res
, RCode::NXDomain
, false, false, true);
925 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
926 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
929 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
930 if (domain
== target
) {
931 setLWResult(res
, 0, false, false, true);
932 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
933 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
936 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
937 setLWResult(res
, 0, true, false, true);
938 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
939 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
942 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
943 setLWResult(res
, 0, true, false, true);
944 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
945 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
949 setLWResult(res
, RCode::NXDomain
, false, false, true);
952 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")) {
953 setLWResult(res
, 0, true, false, true);
954 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
962 vector
<DNSRecord
> ret
;
963 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
964 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
965 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
966 BOOST_CHECK(ret
[0].d_type
== QType::A
);
967 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
970 BOOST_AUTO_TEST_CASE(test_edns_submask_by_domain
) {
971 std::unique_ptr
<SyncRes
> sr
;
976 const DNSName
target("powerdns.com.");
977 SyncRes::addEDNSDomain(target
);
979 EDNSSubnetOpts incomingECS
;
980 incomingECS
.source
= Netmask("192.0.2.128/32");
981 sr
->setIncomingECSFound(true);
982 sr
->setIncomingECS(incomingECS
);
984 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
) {
986 BOOST_REQUIRE(srcmask
);
987 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
991 vector
<DNSRecord
> ret
;
992 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
993 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
996 BOOST_AUTO_TEST_CASE(test_edns_submask_by_addr
) {
997 std::unique_ptr
<SyncRes
> sr
;
1002 const DNSName
target("powerdns.com.");
1003 SyncRes::addEDNSSubnet(Netmask("192.0.2.1/32"));
1005 EDNSSubnetOpts incomingECS
;
1006 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1007 sr
->setIncomingECSFound(true);
1008 sr
->setIncomingECS(incomingECS
);
1010 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
) {
1012 if (isRootServer(ip
)) {
1013 BOOST_REQUIRE(!srcmask
);
1015 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 BOOST_REQUIRE(srcmask
);
1022 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1024 setLWResult(res
, 0, true, false, false);
1025 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1032 vector
<DNSRecord
> ret
;
1033 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1034 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1035 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1036 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1037 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1040 BOOST_AUTO_TEST_CASE(test_following_cname
) {
1041 std::unique_ptr
<SyncRes
> sr
;
1046 const DNSName
target("cname.powerdns.com.");
1047 const DNSName
cnameTarget("cname-target.powerdns.com");
1049 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
) {
1051 if (isRootServer(ip
)) {
1052 setLWResult(res
, 0, false, false, true);
1053 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1054 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1056 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1058 if (domain
== target
) {
1059 setLWResult(res
, 0, true, false, false);
1060 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1063 else if (domain
== cnameTarget
) {
1064 setLWResult(res
, 0, true, false, false);
1065 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1074 vector
<DNSRecord
> ret
;
1075 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1076 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1077 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1078 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1079 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1080 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1081 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1084 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
) {
1085 std::unique_ptr
<SyncRes
> sr
;
1090 const DNSName
target("cname.powerdns.com.");
1091 const DNSName
cnameTarget("cname-target.powerdns.com");
1093 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
) {
1095 if (isRootServer(ip
)) {
1096 setLWResult(res
, 0, false, false, true);
1097 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1098 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1100 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1102 if (domain
== target
) {
1103 setLWResult(res
, RCode::NXDomain
, true, false, false);
1104 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1105 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1106 } else if (domain
== cnameTarget
) {
1107 setLWResult(res
, RCode::NXDomain
, true, false, false);
1108 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1118 vector
<DNSRecord
> ret
;
1119 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1120 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1121 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1122 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1123 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1124 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1126 /* a second time, to check the cache */
1128 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1129 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1130 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1131 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1132 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1133 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1136 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
) {
1137 std::unique_ptr
<SyncRes
> sr
;
1142 /* In this test we directly get the NS server for cname.powerdns.com.,
1143 and we don't know whether it's also authoritative for
1144 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1145 the additional A record for cname-target.powerdns.com. */
1146 const DNSName
target("cname.powerdns.com.");
1147 const DNSName
cnameTarget("cname-target.powerdns.com");
1149 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
) {
1151 if (isRootServer(ip
)) {
1153 setLWResult(res
, 0, false, false, true);
1155 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1156 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1158 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1160 if (domain
== target
) {
1161 setLWResult(res
, 0, true, false, false);
1162 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1163 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1165 } else if (domain
== cnameTarget
) {
1166 setLWResult(res
, 0, true, false, false);
1167 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1177 vector
<DNSRecord
> ret
;
1178 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1179 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1180 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1181 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1182 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1183 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1184 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1185 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1186 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1189 BOOST_AUTO_TEST_CASE(test_cname_loop
) {
1190 std::unique_ptr
<SyncRes
> sr
;
1196 const DNSName
target("cname.powerdns.com.");
1198 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
) {
1202 if (isRootServer(ip
)) {
1204 setLWResult(res
, 0, false, false, true);
1205 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1206 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1208 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1210 if (domain
== target
) {
1211 setLWResult(res
, 0, true, false, false);
1212 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1222 vector
<DNSRecord
> ret
;
1223 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1224 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1225 BOOST_CHECK_GT(ret
.size(), 0);
1226 BOOST_CHECK_EQUAL(count
, 2);
1229 BOOST_AUTO_TEST_CASE(test_cname_depth
) {
1230 std::unique_ptr
<SyncRes
> sr
;
1236 const DNSName
target("cname.powerdns.com.");
1238 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
) {
1240 if (isRootServer(ip
)) {
1242 setLWResult(res
, 0, false, false, true);
1243 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1244 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1246 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1248 setLWResult(res
, 0, true, false, false);
1249 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(depth
) + "-cname.powerdns.com");
1257 vector
<DNSRecord
> ret
;
1258 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1259 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1260 BOOST_CHECK_EQUAL(ret
.size(), depth
);
1261 /* we have an arbitrary limit at 10 when following a CNAME chain */
1262 BOOST_CHECK_EQUAL(depth
, 10 + 2);
1265 BOOST_AUTO_TEST_CASE(test_time_limit
) {
1266 std::unique_ptr
<SyncRes
> sr
;
1272 const DNSName
target("cname.powerdns.com.");
1274 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
) {
1278 if (isRootServer(ip
)) {
1279 setLWResult(res
, 0, false, false, true);
1280 /* Pretend that this query took 2000 ms */
1283 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1284 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1286 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1288 setLWResult(res
, 0, true, false, false);
1289 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1296 /* Set the maximum time to 1 ms */
1297 SyncRes::s_maxtotusec
= 1000;
1300 vector
<DNSRecord
> ret
;
1301 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1304 catch(const ImmediateServFailException
& e
) {
1306 BOOST_CHECK_EQUAL(queries
, 1);
1309 BOOST_AUTO_TEST_CASE(test_referral_depth
) {
1310 std::unique_ptr
<SyncRes
> sr
;
1316 const DNSName
target("www.powerdns.com.");
1318 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
) {
1322 if (isRootServer(ip
)) {
1323 setLWResult(res
, 0, false, false, true);
1325 if (domain
== DNSName("www.powerdns.com.")) {
1326 addRecordToLW(res
, domain
, QType::NS
, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1328 else if (domain
== DNSName("ns.powerdns.com.")) {
1329 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1331 else if (domain
== DNSName("ns1.powerdns.org.")) {
1332 addRecordToLW(res
, domain
, QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1334 else if (domain
== DNSName("ns2.powerdns.org.")) {
1335 addRecordToLW(res
, domain
, QType::NS
, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1337 else if (domain
== DNSName("ns3.powerdns.org.")) {
1338 addRecordToLW(res
, domain
, QType::NS
, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1340 else if (domain
== DNSName("ns4.powerdns.org.")) {
1341 addRecordToLW(res
, domain
, QType::NS
, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1342 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::AUTHORITY
, 172800);
1346 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1348 setLWResult(res
, 0, true, false, false);
1349 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1356 /* Set the maximum depth low */
1357 SyncRes::s_maxdepth
= 10;
1360 vector
<DNSRecord
> ret
;
1361 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1364 catch(const ImmediateServFailException
& e
) {
1368 BOOST_AUTO_TEST_CASE(test_cname_qperq
) {
1369 std::unique_ptr
<SyncRes
> sr
;
1375 const DNSName
target("cname.powerdns.com.");
1377 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
) {
1381 if (isRootServer(ip
)) {
1383 setLWResult(res
, 0, false, false, true);
1384 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1385 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1387 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1389 setLWResult(res
, 0, true, false, false);
1390 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(queries
) + "-cname.powerdns.com");
1397 /* Set the maximum number of questions very low */
1398 SyncRes::s_maxqperq
= 5;
1401 vector
<DNSRecord
> ret
;
1402 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1405 catch(const ImmediateServFailException
& e
) {
1406 BOOST_CHECK_EQUAL(queries
, SyncRes::s_maxqperq
);
1410 BOOST_AUTO_TEST_CASE(test_throttled_server
) {
1411 std::unique_ptr
<SyncRes
> sr
;
1416 const DNSName
target("throttled.powerdns.com.");
1417 const ComboAddress
ns("192.0.2.1:53");
1418 size_t queriesToNS
= 0;
1420 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
) {
1422 if (isRootServer(ip
)) {
1424 setLWResult(res
, 0, false, false, true);
1425 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1426 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1428 } else if (ip
== ns
) {
1432 setLWResult(res
, 0, true, false, false);
1433 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1441 /* mark ns as down */
1442 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, 10000);
1444 vector
<DNSRecord
> ret
;
1445 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1446 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1447 BOOST_CHECK_EQUAL(ret
.size(), 0);
1448 /* we should not have sent any queries to ns */
1449 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1452 BOOST_AUTO_TEST_CASE(test_throttled_server_count
) {
1453 std::unique_ptr
<SyncRes
> sr
;
1458 const ComboAddress
ns("192.0.2.1:53");
1460 const size_t blocks
= 10;
1461 /* mark ns as down for 'blocks' queries */
1462 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, blocks
);
1464 for (size_t idx
= 0; idx
< blocks
; idx
++) {
1465 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1468 /* we have been throttled 'blocks' times, we should not be throttled anymore */
1469 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1472 BOOST_AUTO_TEST_CASE(test_throttled_server_time
) {
1473 std::unique_ptr
<SyncRes
> sr
;
1478 const ComboAddress
ns("192.0.2.1:53");
1480 const size_t seconds
= 1;
1481 /* mark ns as down for 'seconds' seconds */
1482 SyncRes::doThrottle(time(nullptr), ns
, seconds
, 10000);
1484 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1488 /* we should not be throttled anymore */
1489 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1492 BOOST_AUTO_TEST_CASE(test_dont_query_server
) {
1493 std::unique_ptr
<SyncRes
> sr
;
1498 const DNSName
target("throttled.powerdns.com.");
1499 const ComboAddress
ns("192.0.2.1:53");
1500 size_t queriesToNS
= 0;
1502 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
) {
1504 if (isRootServer(ip
)) {
1506 setLWResult(res
, 0, false, false, true);
1507 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1508 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1510 } else if (ip
== ns
) {
1514 setLWResult(res
, 0, true, false, false);
1515 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1523 /* prevent querying this NS */
1524 SyncRes::addDontQuery(Netmask(ns
));
1526 vector
<DNSRecord
> ret
;
1527 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1528 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1529 BOOST_CHECK_EQUAL(ret
.size(), 0);
1530 /* we should not have sent any queries to ns */
1531 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1534 BOOST_AUTO_TEST_CASE(test_root_nx_trust
) {
1535 std::unique_ptr
<SyncRes
> sr
;
1540 const DNSName
target1("powerdns.com.");
1541 const DNSName
target2("notpowerdns.com.");
1542 const ComboAddress
ns("192.0.2.1:53");
1543 size_t queriesCount
= 0;
1545 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
) {
1549 if (isRootServer(ip
)) {
1551 if (domain
== target1
) {
1552 setLWResult(res
, RCode::NXDomain
, true, false, true);
1553 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1556 setLWResult(res
, 0, true, false, true);
1557 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1558 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1562 } else if (ip
== ns
) {
1564 setLWResult(res
, 0, true, false, false);
1565 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1573 vector
<DNSRecord
> ret
;
1574 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1575 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1576 BOOST_CHECK_EQUAL(ret
.size(), 1);
1577 /* one for target1 and one for the entire TLD */
1578 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1581 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1582 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1583 BOOST_CHECK_EQUAL(ret
.size(), 1);
1584 /* one for target1 and one for the entire TLD */
1585 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1587 /* we should have sent only one query */
1588 BOOST_CHECK_EQUAL(queriesCount
, 1);
1591 BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific
) {
1592 std::unique_ptr
<SyncRes
> sr
;
1594 initSR(sr
, true, false);
1598 const DNSName
target1("powerdns.com.");
1599 const DNSName
target2("notpowerdns.com.");
1600 const ComboAddress
ns("192.0.2.1:53");
1601 size_t queriesCount
= 0;
1603 /* This time the root denies target1 with a "com." SOA instead of a "." one.
1604 We should add target1 to the negcache, but not "com.". */
1606 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
) {
1610 if (isRootServer(ip
)) {
1612 if (domain
== target1
) {
1613 setLWResult(res
, RCode::NXDomain
, true, false, true);
1614 addRecordToLW(res
, "com.", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1617 setLWResult(res
, 0, true, false, true);
1618 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1619 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1623 } else if (ip
== ns
) {
1625 setLWResult(res
, 0, true, false, false);
1626 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1634 vector
<DNSRecord
> ret
;
1635 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1636 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1637 BOOST_CHECK_EQUAL(ret
.size(), 1);
1639 /* even with root-nx-trust on and a NX answer from the root,
1640 we should not have cached the entire TLD this time. */
1641 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1644 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1645 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1646 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1647 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1648 BOOST_CHECK_EQUAL(ret
[0].d_name
, target2
);
1649 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress("192.0.2.2"));
1651 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1653 BOOST_CHECK_EQUAL(queriesCount
, 3);
1656 BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust
) {
1657 std::unique_ptr
<SyncRes
> sr
;
1662 const DNSName
target1("powerdns.com.");
1663 const DNSName
target2("notpowerdns.com.");
1664 const ComboAddress
ns("192.0.2.1:53");
1665 size_t queriesCount
= 0;
1667 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
) {
1671 if (isRootServer(ip
)) {
1673 if (domain
== target1
) {
1674 setLWResult(res
, RCode::NXDomain
, true, false, true);
1675 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1678 setLWResult(res
, 0, true, false, true);
1679 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1680 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1684 } else if (ip
== ns
) {
1686 setLWResult(res
, 0, true, false, false);
1687 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1695 SyncRes::s_rootNXTrust
= false;
1697 vector
<DNSRecord
> ret
;
1698 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1699 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1700 BOOST_CHECK_EQUAL(ret
.size(), 1);
1701 /* one for target1 */
1702 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1705 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1706 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1707 BOOST_CHECK_EQUAL(ret
.size(), 1);
1708 /* one for target1 */
1709 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1711 /* we should have sent three queries */
1712 BOOST_CHECK_EQUAL(queriesCount
, 3);
1715 BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response
) {
1716 std::unique_ptr
<SyncRes
> sr
;
1721 const DNSName
target("www.powerdns.com.");
1722 const DNSName
cnameTarget("cname.powerdns.com.");
1724 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
1726 EDNSSubnetOpts incomingECS
;
1727 incomingECS
.source
= Netmask("192.0.2.128/32");
1728 sr
->setIncomingECSFound(true);
1729 sr
->setIncomingECS(incomingECS
);
1731 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
) {
1733 BOOST_REQUIRE(srcmask
);
1734 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1736 if (isRootServer(ip
)) {
1737 setLWResult(res
, 0, false, false, true);
1738 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1739 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1742 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1743 if (domain
== target
) {
1744 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
1745 setLWResult(res
, RCode::NXDomain
, true, false, true);
1746 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1747 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1749 else if (domain
== cnameTarget
) {
1750 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
1751 but we might if we still chase the CNAME. */
1752 setLWResult(res
, RCode::NXDomain
, true, false, true);
1753 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1762 vector
<DNSRecord
> ret
;
1763 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1764 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1765 BOOST_CHECK_EQUAL(ret
.size(), 2);
1766 /* no negative cache entry because the response was variable */
1767 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0);
1770 BOOST_AUTO_TEST_CASE(test_ns_speed
) {
1771 std::unique_ptr
<SyncRes
> sr
;
1776 const DNSName
target("powerdns.com.");
1778 std::map
<ComboAddress
, uint64_t> nsCounts
;
1780 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
) {
1782 if (isRootServer(ip
)) {
1783 setLWResult(res
, 0, false, false, true);
1784 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1785 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1786 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1788 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1789 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1790 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1791 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 3600);
1792 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 3600);
1793 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 3600);
1799 if (ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("192.0.2.2:53")) {
1800 BOOST_CHECK_LT(nsCounts
.size(), 3);
1802 /* let's time out on pdns-public-ns2.powerdns.com. */
1805 else if (ip
== ComboAddress("192.0.2.1:53")) {
1806 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1808 setLWResult(res
, 0, true, false, true);
1809 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1820 gettimeofday(&now
, 0);
1822 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1823 then pdns-public-ns1.powerdns.com. on IPv4 */
1824 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now
);
1825 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now
);
1826 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now
);
1827 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now
);
1828 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now
);
1829 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now
);
1831 vector
<DNSRecord
> ret
;
1832 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1833 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1834 BOOST_CHECK_EQUAL(ret
.size(), 1);
1835 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1836 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.1:53")], 1);
1837 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.2:53")], 1);
1838 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("[2001:DB8::2]:53")], 1);
1841 BOOST_AUTO_TEST_CASE(test_flawed_nsset
) {
1842 std::unique_ptr
<SyncRes
> sr
;
1847 const DNSName
target("powerdns.com.");
1849 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
) {
1851 if (isRootServer(ip
)) {
1852 setLWResult(res
, 0, false, false, true);
1853 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1855 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1858 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1859 setLWResult(res
, 0, true, false, true);
1860 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1867 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1868 time_t now
= time(nullptr);
1869 std::vector
<DNSRecord
> records
;
1870 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1871 addRecordToList(records
, target
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, now
+ 3600);
1873 t_RC
->replace(now
, target
, QType(QType::NS
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1875 vector
<DNSRecord
> ret
;
1876 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1877 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1878 BOOST_CHECK_EQUAL(ret
.size(), 1);
1881 BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset
) {
1882 std::unique_ptr
<SyncRes
> sr
;
1887 const DNSName
target("powerdns.com.");
1888 size_t queriesCount
= 0;
1890 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
) {
1894 if (isRootServer(ip
) && domain
== target
) {
1895 setLWResult(res
, 0, false, false, true);
1896 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1897 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1899 } else if (domain
== DNSName("pdns-public-ns2.powerdns.com.") || domain
== DNSName("pdns-public-ns3.powerdns.com.")){
1900 setLWResult(res
, 0, true, false, true);
1901 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1908 vector
<DNSRecord
> ret
;
1909 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1910 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1911 BOOST_CHECK_EQUAL(ret
.size(), 0);
1912 /* one query to get NSs, then A and AAAA for each NS */
1913 BOOST_CHECK_EQUAL(queriesCount
, 5);
1916 BOOST_AUTO_TEST_CASE(test_cache_hit
) {
1917 std::unique_ptr
<SyncRes
> sr
;
1922 const DNSName
target("powerdns.com.");
1924 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
) {
1929 /* we populate the cache with eveything we need */
1930 time_t now
= time(nullptr);
1931 std::vector
<DNSRecord
> records
;
1932 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1934 addRecordToList(records
, target
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, now
+ 3600);
1935 t_RC
->replace(now
, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1937 vector
<DNSRecord
> ret
;
1938 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1939 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1940 BOOST_CHECK_EQUAL(ret
.size(), 1);
1943 BOOST_AUTO_TEST_CASE(test_no_rd
) {
1944 std::unique_ptr
<SyncRes
> sr
;
1949 const DNSName
target("powerdns.com.");
1950 size_t queriesCount
= 0;
1954 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
) {
1960 vector
<DNSRecord
> ret
;
1961 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1962 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1963 BOOST_CHECK_EQUAL(ret
.size(), 0);
1964 BOOST_CHECK_EQUAL(queriesCount
, 0);
1967 BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl
) {
1968 std::unique_ptr
<SyncRes
> sr
;
1973 const DNSName
target("cachettl.powerdns.com.");
1974 const ComboAddress
ns("192.0.2.1:53");
1976 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
) {
1978 if (isRootServer(ip
)) {
1980 setLWResult(res
, 0, false, false, true);
1981 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1982 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 7200);
1984 } else if (ip
== ns
) {
1986 setLWResult(res
, 0, true, false, false);
1987 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
1995 const time_t now
= time(nullptr);
1996 SyncRes::s_minimumTTL
= 60;
1997 SyncRes::s_maxcachettl
= 3600;
1999 vector
<DNSRecord
> ret
;
2000 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2001 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2002 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2003 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumTTL
);
2005 const ComboAddress who
;
2006 vector
<DNSRecord
> cached
;
2007 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
2008 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2009 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2010 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
2013 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
2014 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2015 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2016 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
2019 BOOST_AUTO_TEST_CASE(test_cache_expired_ttl
) {
2020 std::unique_ptr
<SyncRes
> sr
;
2025 const DNSName
target("powerdns.com.");
2027 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
) {
2029 if (isRootServer(ip
)) {
2030 setLWResult(res
, 0, false, false, true);
2031 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2033 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2036 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2037 setLWResult(res
, 0, true, false, true);
2038 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2045 /* we populate the cache with entries that expired 60s ago*/
2046 time_t now
= time(nullptr);
2047 std::vector
<DNSRecord
> records
;
2048 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
2049 addRecordToList(records
, target
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, now
- 60);
2051 t_RC
->replace(now
- 3600, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
2053 vector
<DNSRecord
> ret
;
2054 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2055 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2056 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2057 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
2058 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
2061 BOOST_AUTO_TEST_CASE(test_delegation_only
) {
2062 std::unique_ptr
<SyncRes
> sr
;
2067 /* Thanks, Verisign */
2068 SyncRes::addDelegationOnly(DNSName("com."));
2069 SyncRes::addDelegationOnly(DNSName("net."));
2071 const DNSName
target("nx-powerdns.com.");
2073 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
) {
2075 if (isRootServer(ip
)) {
2076 setLWResult(res
, 0, false, false, true);
2077 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2078 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2080 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2082 setLWResult(res
, 0, true, false, true);
2083 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2090 vector
<DNSRecord
> ret
;
2091 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2092 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2093 BOOST_CHECK_EQUAL(ret
.size(), 0);
2096 BOOST_AUTO_TEST_CASE(test_unauth_any
) {
2097 std::unique_ptr
<SyncRes
> sr
;
2102 const DNSName
target("powerdns.com.");
2104 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
) {
2106 if (isRootServer(ip
)) {
2107 setLWResult(res
, 0, false, false, true);
2108 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2109 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2111 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2113 setLWResult(res
, 0, false, false, true);
2114 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2121 vector
<DNSRecord
> ret
;
2122 int res
= sr
->beginResolve(target
, QType(QType::ANY
), QClass::IN
, ret
);
2123 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2124 BOOST_CHECK_EQUAL(ret
.size(), 0);
2127 BOOST_AUTO_TEST_CASE(test_no_data
) {
2128 std::unique_ptr
<SyncRes
> sr
;
2133 const DNSName
target("powerdns.com.");
2135 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
) {
2137 setLWResult(res
, 0, true, false, true);
2141 vector
<DNSRecord
> ret
;
2142 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2143 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2144 BOOST_CHECK_EQUAL(ret
.size(), 0);
2147 BOOST_AUTO_TEST_CASE(test_skip_opt_any
) {
2148 std::unique_ptr
<SyncRes
> sr
;
2153 const DNSName
target("powerdns.com.");
2155 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
) {
2157 setLWResult(res
, 0, true, false, true);
2158 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2159 addRecordToLW(res
, domain
, QType::ANY
, "0 0");
2160 addRecordToLW(res
, domain
, QType::OPT
, "");
2164 vector
<DNSRecord
> ret
;
2165 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2166 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2167 BOOST_CHECK_EQUAL(ret
.size(), 1);
2170 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec
) {
2171 std::unique_ptr
<SyncRes
> sr
;
2176 const DNSName
target("powerdns.com.");
2178 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
) {
2180 setLWResult(res
, 0, true, false, true);
2181 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2182 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2183 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2184 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2185 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2189 vector
<DNSRecord
> ret
;
2190 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2191 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2192 BOOST_CHECK_EQUAL(ret
.size(), 1);
2195 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec
) {
2196 std::unique_ptr
<SyncRes
> sr
;
2201 const DNSName
target("powerdns.com.");
2203 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
) {
2205 setLWResult(res
, 0, true, false, true);
2206 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2207 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2208 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2209 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2210 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2214 vector
<DNSRecord
> ret
;
2215 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2216 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2217 BOOST_CHECK_EQUAL(ret
.size(), 4);
2220 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec
) {
2221 std::unique_ptr
<SyncRes
> sr
;
2226 const DNSName
target("powerdns.com.");
2228 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
) {
2230 setLWResult(res
, RCode::NXDomain
, true, false, true);
2231 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2232 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2233 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2234 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2235 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2239 vector
<DNSRecord
> ret
;
2240 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2241 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2242 BOOST_CHECK_EQUAL(ret
.size(), 1);
2245 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec
) {
2246 std::unique_ptr
<SyncRes
> sr
;
2251 const DNSName
target("powerdns.com.");
2253 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
) {
2255 setLWResult(res
, RCode::NXDomain
, true, false, true);
2256 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2257 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2258 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2259 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2260 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2264 vector
<DNSRecord
> ret
;
2265 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2266 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2267 BOOST_CHECK_EQUAL(ret
.size(), 4);
2270 BOOST_AUTO_TEST_CASE(test_qclass_none
) {
2271 std::unique_ptr
<SyncRes
> sr
;
2276 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
2277 size_t queriesCount
= 0;
2279 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
) {
2285 const DNSName
target("powerdns.com.");
2286 vector
<DNSRecord
> ret
;
2287 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::NONE
, ret
);
2288 BOOST_CHECK_EQUAL(res
, -1);
2289 BOOST_CHECK_EQUAL(ret
.size(), 0);
2290 BOOST_CHECK_EQUAL(queriesCount
, 0);
2293 BOOST_AUTO_TEST_CASE(test_special_types
) {
2294 std::unique_ptr
<SyncRes
> sr
;
2299 /* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
2300 size_t queriesCount
= 0;
2302 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
) {
2304 cerr
<<"asyncresolve called to ask "<<ip
.toStringWithPort()<<" about "<<domain
.toString()<<" / "<<QType(type
).getName()<<" over "<<(doTCP
? "TCP" : "UDP")<<" (rd: "<<sendRDQuery
<<", EDNS0 level: "<<EDNS0Level
<<")"<<endl
;
2309 const DNSName
target("powerdns.com.");
2310 vector
<DNSRecord
> ret
;
2311 int res
= sr
->beginResolve(target
, QType(QType::AXFR
), QClass::IN
, ret
);
2312 BOOST_CHECK_EQUAL(res
, -1);
2313 BOOST_CHECK_EQUAL(ret
.size(), 0);
2314 BOOST_CHECK_EQUAL(queriesCount
, 0);
2316 res
= sr
->beginResolve(target
, QType(QType::IXFR
), QClass::IN
, ret
);
2317 BOOST_CHECK_EQUAL(res
, -1);
2318 BOOST_CHECK_EQUAL(ret
.size(), 0);
2319 BOOST_CHECK_EQUAL(queriesCount
, 0);
2321 res
= sr
->beginResolve(target
, QType(QType::RRSIG
), QClass::IN
, ret
);
2322 BOOST_CHECK_EQUAL(res
, -1);
2323 BOOST_CHECK_EQUAL(ret
.size(), 0);
2324 BOOST_CHECK_EQUAL(queriesCount
, 0);
2326 res
= sr
->beginResolve(target
, QType(QType::NSEC3
), QClass::IN
, ret
);
2327 BOOST_CHECK_EQUAL(res
, -1);
2328 BOOST_CHECK_EQUAL(ret
.size(), 0);
2329 BOOST_CHECK_EQUAL(queriesCount
, 0);
2332 BOOST_AUTO_TEST_CASE(test_special_names
) {
2333 std::unique_ptr
<SyncRes
> sr
;
2338 /* special names should be handled internally */
2340 size_t queriesCount
= 0;
2342 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
) {
2348 vector
<DNSRecord
> ret
;
2349 int res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
2350 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2351 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2352 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2353 BOOST_CHECK_EQUAL(queriesCount
, 0);
2356 res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
2357 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2358 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2359 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2360 BOOST_CHECK_EQUAL(queriesCount
, 0);
2363 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
);
2364 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2365 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2366 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2367 BOOST_CHECK_EQUAL(queriesCount
, 0);
2370 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
);
2371 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2372 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2373 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2374 BOOST_CHECK_EQUAL(queriesCount
, 0);
2377 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::A
), QClass::IN
, ret
);
2378 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2379 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2380 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2381 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), "127.0.0.1");
2382 BOOST_CHECK_EQUAL(queriesCount
, 0);
2385 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::AAAA
), QClass::IN
, ret
);
2386 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2387 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2388 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
2389 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(ret
[0])->getCA().toString(), "::1");
2390 BOOST_CHECK_EQUAL(queriesCount
, 0);
2393 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::ANY
), QClass::IN
, ret
);
2394 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2395 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2396 for (const auto& rec
: ret
) {
2397 BOOST_REQUIRE((rec
.d_type
== QType::A
) || rec
.d_type
== QType::AAAA
);
2398 if (rec
.d_type
== QType::A
) {
2399 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(rec
)->getCA().toString(), "127.0.0.1");
2402 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(rec
)->getCA().toString(), "::1");
2405 BOOST_CHECK_EQUAL(queriesCount
, 0);
2408 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2409 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2410 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2411 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2412 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2413 BOOST_CHECK_EQUAL(queriesCount
, 0);
2416 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2417 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2418 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2419 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2420 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2421 BOOST_CHECK_EQUAL(queriesCount
, 0);
2424 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2425 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2426 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2427 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2428 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2429 BOOST_CHECK_EQUAL(queriesCount
, 0);
2432 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2433 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2434 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2435 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2436 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2437 BOOST_CHECK_EQUAL(queriesCount
, 0);
2440 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2441 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2442 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2443 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2444 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2445 BOOST_CHECK_EQUAL(queriesCount
, 0);
2448 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2449 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2450 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2451 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2452 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2453 BOOST_CHECK_EQUAL(queriesCount
, 0);
2456 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz
) {
2457 std::unique_ptr
<SyncRes
> sr
;
2462 const DNSName
target("rpz.powerdns.com.");
2463 const ComboAddress
ns("192.0.2.1:53");
2465 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
) {
2467 if (isRootServer(ip
)) {
2468 setLWResult(res
, false, true, false, true);
2469 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2470 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2472 } else if (ip
== ns
) {
2474 setLWResult(res
, 0, true, false, true);
2475 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2482 DNSFilterEngine::Policy pol
;
2483 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2484 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2485 zone
->setName("Unit test policy 0");
2486 zone
->addNSIPTrigger(Netmask(ns
, 32), pol
);
2487 auto luaconfsCopy
= g_luaconfs
.getCopy();
2488 luaconfsCopy
.dfe
.addZone(zone
);
2489 g_luaconfs
.setState(luaconfsCopy
);
2491 vector
<DNSRecord
> ret
;
2492 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2493 BOOST_CHECK_EQUAL(res
, -2);
2494 BOOST_CHECK_EQUAL(ret
.size(), 0);
2497 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz
) {
2498 std::unique_ptr
<SyncRes
> sr
;
2503 const DNSName
target("rpz.powerdns.com.");
2504 const ComboAddress
ns("[2001:DB8::42]:53");
2506 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
) {
2508 if (isRootServer(ip
)) {
2509 setLWResult(res
, 0, false, false, true);
2510 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2511 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2513 } else if (ip
== ns
) {
2515 setLWResult(res
, 0, true, false, true);
2516 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2523 DNSFilterEngine::Policy pol
;
2524 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2525 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2526 zone
->setName("Unit test policy 0");
2527 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2528 auto luaconfsCopy
= g_luaconfs
.getCopy();
2529 luaconfsCopy
.dfe
.addZone(zone
);
2530 g_luaconfs
.setState(luaconfsCopy
);
2532 vector
<DNSRecord
> ret
;
2533 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2534 BOOST_CHECK_EQUAL(res
, -2);
2535 BOOST_CHECK_EQUAL(ret
.size(), 0);
2538 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz
) {
2539 std::unique_ptr
<SyncRes
> sr
;
2544 const DNSName
target("rpz.powerdns.com.");
2545 const ComboAddress
ns("192.0.2.1:53");
2546 const DNSName
nsName("ns1.powerdns.com.");
2548 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
) {
2550 if (isRootServer(ip
)) {
2551 setLWResult(res
, 0, false, false, true);
2552 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2553 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2555 } else if (ip
== ns
) {
2557 setLWResult(res
, 0, true, false, true);
2558 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2565 DNSFilterEngine::Policy pol
;
2566 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2567 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2568 zone
->setName("Unit test policy 0");
2569 zone
->addNSTrigger(nsName
, pol
);
2570 auto luaconfsCopy
= g_luaconfs
.getCopy();
2571 luaconfsCopy
.dfe
.addZone(zone
);
2572 g_luaconfs
.setState(luaconfsCopy
);
2574 vector
<DNSRecord
> ret
;
2575 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2576 BOOST_CHECK_EQUAL(res
, -2);
2577 BOOST_CHECK_EQUAL(ret
.size(), 0);
2580 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled
) {
2581 std::unique_ptr
<SyncRes
> sr
;
2586 const DNSName
target("rpz.powerdns.com.");
2587 const ComboAddress
ns("192.0.2.1:53");
2588 const DNSName
nsName("ns1.powerdns.com.");
2590 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
) {
2592 if (isRootServer(ip
)) {
2593 setLWResult(res
, 0, false, false, true);
2594 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2595 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2597 } else if (ip
== ns
) {
2599 setLWResult(res
, 0, true, false, true);
2600 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2607 DNSFilterEngine::Policy pol
;
2608 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2609 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2610 zone
->setName("Unit test policy 0");
2611 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2612 zone
->addNSTrigger(nsName
, pol
);
2613 auto luaconfsCopy
= g_luaconfs
.getCopy();
2614 luaconfsCopy
.dfe
.addZone(zone
);
2615 g_luaconfs
.setState(luaconfsCopy
);
2617 /* RPZ is disabled for this query, we should not be blocked */
2618 sr
->setWantsRPZ(false);
2620 vector
<DNSRecord
> ret
;
2621 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2622 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2623 BOOST_CHECK_EQUAL(ret
.size(), 1);
2626 BOOST_AUTO_TEST_CASE(test_forward_zone_nord
) {
2627 std::unique_ptr
<SyncRes
> sr
;
2632 const DNSName
target("powerdns.com.");
2633 const ComboAddress
ns("192.0.2.1:53");
2634 const ComboAddress
forwardedNS("192.0.2.42:53");
2636 SyncRes::AuthDomain ad
;
2637 ad
.d_rdForward
= false;
2638 ad
.d_servers
.push_back(forwardedNS
);
2639 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2641 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
) {
2643 if (ip
== forwardedNS
) {
2644 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2646 setLWResult(res
, 0, true, false, true);
2647 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2654 /* simulate a no-RD query */
2657 vector
<DNSRecord
> ret
;
2658 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2659 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2660 BOOST_CHECK_EQUAL(ret
.size(), 1);
2663 BOOST_AUTO_TEST_CASE(test_forward_zone_rd
) {
2664 std::unique_ptr
<SyncRes
> sr
;
2669 const DNSName
target("powerdns.com.");
2670 const ComboAddress
ns("192.0.2.1:53");
2671 const ComboAddress
forwardedNS("192.0.2.42:53");
2673 SyncRes::AuthDomain ad
;
2674 ad
.d_rdForward
= false;
2675 ad
.d_servers
.push_back(forwardedNS
);
2676 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2678 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
) {
2680 if (ip
== forwardedNS
) {
2681 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2683 setLWResult(res
, 0, true, false, true);
2684 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2691 vector
<DNSRecord
> ret
;
2692 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2693 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2694 BOOST_CHECK_EQUAL(ret
.size(), 1);
2697 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord
) {
2698 std::unique_ptr
<SyncRes
> sr
;
2703 const DNSName
target("powerdns.com.");
2704 const ComboAddress
ns("192.0.2.1:53");
2705 const ComboAddress
forwardedNS("192.0.2.42:53");
2707 SyncRes::AuthDomain ad
;
2708 ad
.d_rdForward
= true;
2709 ad
.d_servers
.push_back(forwardedNS
);
2710 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2712 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
) {
2714 if (ip
== forwardedNS
) {
2715 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2717 setLWResult(res
, 0, true, false, true);
2718 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2725 /* simulate a no-RD query */
2728 vector
<DNSRecord
> ret
;
2729 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2730 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2731 BOOST_CHECK_EQUAL(ret
.size(), 1);
2734 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd
) {
2735 std::unique_ptr
<SyncRes
> sr
;
2740 const DNSName
target("powerdns.com.");
2741 const ComboAddress
ns("192.0.2.1:53");
2742 const ComboAddress
forwardedNS("192.0.2.42:53");
2744 SyncRes::AuthDomain ad
;
2745 ad
.d_rdForward
= true;
2746 ad
.d_servers
.push_back(forwardedNS
);
2747 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2749 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
) {
2751 if (ip
== forwardedNS
) {
2752 BOOST_CHECK_EQUAL(sendRDQuery
, true);
2754 setLWResult(res
, 0, true, false, true);
2755 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2762 vector
<DNSRecord
> ret
;
2763 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2764 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2765 BOOST_CHECK_EQUAL(ret
.size(), 1);
2768 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_oob
) {
2769 std::unique_ptr
<SyncRes
> sr
;
2771 initSR(sr
, true, false);
2775 size_t queriesCount
= 0;
2776 const DNSName
target("test.xx.");
2777 const ComboAddress
targetAddr("127.0.0.1");
2778 const DNSName
ns("localhost.");
2779 const ComboAddress
nsAddr("127.0.0.1");
2780 const DNSName
authZone("test.xx");
2782 SyncRes::AuthDomain ad
;
2784 dr
.d_place
= DNSResourceRecord::ANSWER
;
2785 dr
.d_name
= authZone
;
2786 dr
.d_type
= QType::NS
;
2788 dr
.d_content
= std::make_shared
<NSRecordContent
>("localhost.");
2789 ad
.d_records
.insert(dr
);
2791 dr
.d_place
= DNSResourceRecord::ANSWER
;
2792 dr
.d_name
= authZone
;
2793 dr
.d_type
= QType::A
;
2795 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
2796 ad
.d_records
.insert(dr
);
2798 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
2800 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
) {
2805 vector
<DNSRecord
> ret
;
2806 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2807 BOOST_CHECK_EQUAL(res
, 0);
2808 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2809 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2810 BOOST_CHECK_EQUAL(queriesCount
, 0);
2811 BOOST_CHECK(sr
->wasOutOfBand());
2813 /* a second time, to check that the OOB flag is set when the query cache is used */
2815 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2816 BOOST_CHECK_EQUAL(res
, 0);
2817 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2818 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2819 BOOST_CHECK_EQUAL(queriesCount
, 0);
2820 BOOST_CHECK(sr
->wasOutOfBand());
2823 BOOST_AUTO_TEST_CASE(test_auth_zone
) {
2824 std::unique_ptr
<SyncRes
> sr
;
2829 size_t queriesCount
= 0;
2830 const DNSName
target("powerdns.com.");
2831 const ComboAddress
addr("192.0.2.5");
2833 SyncRes::AuthDomain ad
;
2836 dr
.d_place
= DNSResourceRecord::ANSWER
;
2838 dr
.d_type
= QType::SOA
;
2840 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2841 ad
.d_records
.insert(dr
);
2843 dr
.d_place
= DNSResourceRecord::ANSWER
;
2845 dr
.d_type
= QType::A
;
2847 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
2848 ad
.d_records
.insert(dr
);
2850 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2851 (*map
)[target
] = ad
;
2852 SyncRes::setDomainMap(map
);
2854 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
) {
2857 setLWResult(res
, 0, true, false, true);
2858 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2862 vector
<DNSRecord
> ret
;
2863 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2864 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2865 BOOST_CHECK_EQUAL(ret
.size(), 1);
2866 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2867 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
2868 BOOST_CHECK_EQUAL(queriesCount
, 0);
2871 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob
) {
2872 std::unique_ptr
<SyncRes
> sr
;
2877 size_t queriesCount
= 0;
2878 const DNSName
target("powerdns.com.");
2879 const DNSName
authZone("internal.powerdns.com.");
2880 const ComboAddress
addr("192.0.2.5");
2882 SyncRes::AuthDomain ad
;
2883 ad
.d_name
= authZone
;
2885 dr
.d_place
= DNSResourceRecord::ANSWER
;
2886 dr
.d_name
= authZone
;
2887 dr
.d_type
= QType::SOA
;
2889 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2890 ad
.d_records
.insert(dr
);
2892 dr
.d_place
= DNSResourceRecord::ANSWER
;
2893 dr
.d_name
= authZone
;
2894 dr
.d_type
= QType::A
;
2896 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
2897 ad
.d_records
.insert(dr
);
2899 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2900 (*map
)[authZone
] = ad
;
2901 SyncRes::setDomainMap(map
);
2903 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
) {
2907 if (domain
== target
) {
2908 setLWResult(res
, 0, true, false, true);
2909 addRecordToLW(res
, target
, QType::CNAME
, authZone
.toString(), DNSResourceRecord::ANSWER
, 3600);
2916 vector
<DNSRecord
> ret
;
2917 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2918 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2919 BOOST_CHECK_EQUAL(ret
.size(), 2);
2920 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2921 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), authZone
.toString());
2922 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2923 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
2924 BOOST_CHECK_EQUAL(queriesCount
, 1);
2927 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb
) {
2928 std::unique_ptr
<SyncRes
> sr
;
2933 size_t queriesCount
= 0;
2934 const DNSName
target("powerdns.com.");
2935 const DNSName
externalCNAME("www.open-xchange.com.");
2936 const ComboAddress
addr("192.0.2.5");
2938 SyncRes::AuthDomain ad
;
2941 dr
.d_place
= DNSResourceRecord::ANSWER
;
2943 dr
.d_type
= QType::SOA
;
2945 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2946 ad
.d_records
.insert(dr
);
2948 dr
.d_place
= DNSResourceRecord::ANSWER
;
2950 dr
.d_type
= QType::CNAME
;
2952 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(externalCNAME
);
2953 ad
.d_records
.insert(dr
);
2955 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2956 (*map
)[target
] = ad
;
2957 SyncRes::setDomainMap(map
);
2959 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
) {
2963 if (domain
== externalCNAME
) {
2964 setLWResult(res
, 0, true, false, true);
2965 addRecordToLW(res
, externalCNAME
, QType::A
, addr
.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_CHECK_EQUAL(ret
.size(), 2);
2976 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2977 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), externalCNAME
.toString());
2978 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2979 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
2980 BOOST_CHECK_EQUAL(queriesCount
, 1);
2983 BOOST_AUTO_TEST_CASE(test_auth_zone_nodata
) {
2984 std::unique_ptr
<SyncRes
> sr
;
2989 size_t queriesCount
= 0;
2990 const DNSName
target("nodata.powerdns.com.");
2991 const DNSName
authZone("powerdns.com");
2993 SyncRes::AuthDomain ad
;
2994 ad
.d_name
= authZone
;
2996 dr
.d_place
= DNSResourceRecord::ANSWER
;
2998 dr
.d_type
= QType::A
;
3000 dr
.d_content
= std::make_shared
<ARecordContent
>(ComboAddress("192.0.2.1"));
3001 ad
.d_records
.insert(dr
);
3003 dr
.d_place
= DNSResourceRecord::ANSWER
;
3004 dr
.d_name
= authZone
;
3005 dr
.d_type
= QType::SOA
;
3007 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3008 ad
.d_records
.insert(dr
);
3010 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3011 (*map
)[authZone
] = ad
;
3012 SyncRes::setDomainMap(map
);
3014 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
) {
3021 vector
<DNSRecord
> ret
;
3022 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3023 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3024 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3025 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3026 BOOST_CHECK_EQUAL(queriesCount
, 0);
3029 BOOST_AUTO_TEST_CASE(test_auth_zone_nx
) {
3030 std::unique_ptr
<SyncRes
> sr
;
3035 size_t queriesCount
= 0;
3036 const DNSName
target("nx.powerdns.com.");
3037 const DNSName
authZone("powerdns.com");
3039 SyncRes::AuthDomain ad
;
3040 ad
.d_name
= authZone
;
3042 dr
.d_place
= DNSResourceRecord::ANSWER
;
3043 dr
.d_name
= DNSName("powerdns.com.");
3044 dr
.d_type
= QType::SOA
;
3046 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3047 ad
.d_records
.insert(dr
);
3049 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3050 (*map
)[authZone
] = ad
;
3051 SyncRes::setDomainMap(map
);
3053 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
) {
3060 vector
<DNSRecord
> ret
;
3061 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3062 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
3063 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3064 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3065 BOOST_CHECK_EQUAL(queriesCount
, 0);
3068 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation
) {
3069 std::unique_ptr
<SyncRes
> sr
;
3074 size_t queriesCount
= 0;
3075 const DNSName
target("www.test.powerdns.com.");
3076 const ComboAddress
targetAddr("192.0.2.2");
3077 const DNSName
ns("ns1.test.powerdns.com.");
3078 const ComboAddress
nsAddr("192.0.2.1");
3079 const DNSName
authZone("powerdns.com");
3081 SyncRes::AuthDomain ad
;
3082 ad
.d_name
= authZone
;
3084 dr
.d_place
= DNSResourceRecord::ANSWER
;
3085 dr
.d_name
= authZone
;
3086 dr
.d_type
= QType::SOA
;
3088 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3089 ad
.d_records
.insert(dr
);
3091 dr
.d_place
= DNSResourceRecord::ANSWER
;
3092 dr
.d_name
= DNSName("test.powerdns.com.");
3093 dr
.d_type
= QType::NS
;
3095 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3096 ad
.d_records
.insert(dr
);
3098 dr
.d_place
= DNSResourceRecord::ANSWER
;
3100 dr
.d_type
= QType::A
;
3102 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3103 ad
.d_records
.insert(dr
);
3105 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3106 (*map
)[authZone
] = ad
;
3107 SyncRes::setDomainMap(map
);
3109 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
) {
3112 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3113 setLWResult(res
, 0, true, false, true);
3114 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3121 vector
<DNSRecord
> ret
;
3122 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3123 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3124 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3125 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3126 BOOST_CHECK_EQUAL(queriesCount
, 1);
3129 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point
) {
3130 std::unique_ptr
<SyncRes
> sr
;
3135 size_t queriesCount
= 0;
3136 const DNSName
target("test.powerdns.com.");
3137 const ComboAddress
targetAddr("192.0.2.2");
3138 const DNSName
ns("ns1.test.powerdns.com.");
3139 const ComboAddress
nsAddr("192.0.2.1");
3140 const DNSName
authZone("powerdns.com");
3142 SyncRes::AuthDomain ad
;
3143 ad
.d_name
= authZone
;
3145 dr
.d_place
= DNSResourceRecord::ANSWER
;
3146 dr
.d_name
= authZone
;
3147 dr
.d_type
= QType::SOA
;
3149 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3150 ad
.d_records
.insert(dr
);
3152 dr
.d_place
= DNSResourceRecord::ANSWER
;
3153 dr
.d_name
= DNSName("test.powerdns.com.");
3154 dr
.d_type
= QType::NS
;
3156 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3157 ad
.d_records
.insert(dr
);
3159 dr
.d_place
= DNSResourceRecord::ANSWER
;
3161 dr
.d_type
= QType::A
;
3163 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3164 ad
.d_records
.insert(dr
);
3166 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3167 (*map
)[authZone
] = ad
;
3168 SyncRes::setDomainMap(map
);
3170 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
) {
3174 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3175 setLWResult(res
, 0, true, false, true);
3176 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3183 vector
<DNSRecord
> ret
;
3184 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3185 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3186 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3187 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3188 BOOST_CHECK_EQUAL(queriesCount
, 1);
3191 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard
) {
3192 std::unique_ptr
<SyncRes
> sr
;
3197 size_t queriesCount
= 0;
3198 const DNSName
target("test.powerdns.com.");
3199 const ComboAddress
targetAddr("192.0.2.2");
3200 const DNSName
authZone("powerdns.com");
3202 SyncRes::AuthDomain ad
;
3203 ad
.d_name
= authZone
;
3205 dr
.d_place
= DNSResourceRecord::ANSWER
;
3206 dr
.d_name
= authZone
;
3207 dr
.d_type
= QType::SOA
;
3209 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3210 ad
.d_records
.insert(dr
);
3212 dr
.d_place
= DNSResourceRecord::ANSWER
;
3213 dr
.d_name
= DNSName("*.powerdns.com.");
3214 dr
.d_type
= QType::A
;
3216 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3217 ad
.d_records
.insert(dr
);
3219 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3220 (*map
)[authZone
] = ad
;
3221 SyncRes::setDomainMap(map
);
3223 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
) {
3230 vector
<DNSRecord
> ret
;
3231 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3232 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3233 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3234 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3235 BOOST_CHECK_EQUAL(queriesCount
, 0);
3238 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata
) {
3239 std::unique_ptr
<SyncRes
> sr
;
3244 size_t queriesCount
= 0;
3245 const DNSName
target("test.powerdns.com.");
3246 const ComboAddress
targetAddr("192.0.2.2");
3247 const DNSName
authZone("powerdns.com");
3249 SyncRes::AuthDomain ad
;
3250 ad
.d_name
= authZone
;
3252 dr
.d_place
= DNSResourceRecord::ANSWER
;
3253 dr
.d_name
= authZone
;
3254 dr
.d_type
= QType::SOA
;
3256 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3257 ad
.d_records
.insert(dr
);
3259 dr
.d_place
= DNSResourceRecord::ANSWER
;
3260 dr
.d_name
= DNSName("*.powerdns.com.");
3261 dr
.d_type
= QType::A
;
3263 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3264 ad
.d_records
.insert(dr
);
3266 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3267 (*map
)[authZone
] = ad
;
3268 SyncRes::setDomainMap(map
);
3270 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
) {
3277 vector
<DNSRecord
> ret
;
3278 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3279 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3280 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3281 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3282 BOOST_CHECK_EQUAL(queriesCount
, 0);
3285 BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only
) {
3286 std::unique_ptr
<SyncRes
> sr
;
3291 size_t queriesCount
= 0;
3292 const DNSName
target("powerdns.com.");
3293 const ComboAddress
addr("192.0.2.5");
3295 SyncRes::AuthDomain ad
;
3298 dr
.d_place
= DNSResourceRecord::ANSWER
;
3300 dr
.d_type
= QType::SOA
;
3302 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3303 ad
.d_records
.insert(dr
);
3305 dr
.d_place
= DNSResourceRecord::ANSWER
;
3307 dr
.d_type
= QType::A
;
3309 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3310 ad
.d_records
.insert(dr
);
3312 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3313 (*map
)[target
] = ad
;
3314 SyncRes::setDomainMap(map
);
3316 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
) {
3319 setLWResult(res
, 0, true, false, true);
3320 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
3324 /* simulate a no-RD query */
3327 vector
<DNSRecord
> ret
;
3328 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3329 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3330 BOOST_CHECK_EQUAL(ret
.size(), 1);
3331 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3332 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3333 BOOST_CHECK_EQUAL(queriesCount
, 0);
3336 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig
) {
3339 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3340 dcke
->create(dcke
->getBits());
3341 // cerr<<dcke->convertToISC()<<endl;
3342 DNSSECPrivateKey dpk
;
3346 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
3347 recordcontents
.push_back(getRecordContent(QType::A
, "192.0.2.1"));
3349 DNSName
qname("powerdns.com.");
3351 time_t now
= time(nullptr);
3352 RRSIGRecordContent rrc
;
3353 /* this RRSIG is valid for the current second only */
3354 computeRRSIG(dpk
, qname
, qname
, QType::A
, 600, 0, rrc
, recordcontents
, boost::none
, now
);
3357 keyset
.insert(std::make_shared
<DNSKEYRecordContent
>(dpk
.getDNSKEY()));
3359 std::vector
<std::shared_ptr
<RRSIGRecordContent
> > sigs
;
3360 sigs
.push_back(std::make_shared
<RRSIGRecordContent
>(rrc
));
3362 BOOST_CHECK(validateWithKeySet(now
, qname
, recordcontents
, sigs
, keyset
));
3365 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk
) {
3366 std::unique_ptr
<SyncRes
> sr
;
3369 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3372 const DNSName
target(".");
3375 auto luaconfsCopy
= g_luaconfs
.getCopy();
3376 luaconfsCopy
.dsAnchors
.clear();
3377 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3378 g_luaconfs
.setState(luaconfsCopy
);
3380 size_t queriesCount
= 0;
3382 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
) {
3385 if (domain
== target
&& type
== QType::NS
) {
3387 setLWResult(res
, 0, true, false, true);
3388 char addr
[] = "a.root-servers.net.";
3389 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3391 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3394 addRRSIG(keys
, res
->d_records
, domain
, 300);
3396 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3397 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3400 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3402 setLWResult(res
, 0, true, false, true);
3404 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3405 addRRSIG(keys
, res
->d_records
, domain
, 300);
3413 vector
<DNSRecord
> ret
;
3414 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3415 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3416 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3417 /* 13 NS + 1 RRSIG */
3418 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3419 BOOST_CHECK_EQUAL(queriesCount
, 2);
3421 /* again, to test the cache */
3423 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3424 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3425 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3426 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3427 BOOST_CHECK_EQUAL(queriesCount
, 2);
3430 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk
) {
3431 std::unique_ptr
<SyncRes
> sr
;
3434 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3437 const DNSName
target(".");
3438 testkeysset_t zskeys
;
3439 testkeysset_t kskeys
;
3441 /* Generate key material for "." */
3442 auto dckeZ
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3443 dckeZ
->create(dckeZ
->getBits());
3444 DNSSECPrivateKey ksk
;
3447 DSRecordContent kskds
= makeDSFromDNSKey(target
, ksk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3449 auto dckeK
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3450 dckeK
->create(dckeK
->getBits());
3451 DNSSECPrivateKey zsk
;
3454 DSRecordContent zskds
= makeDSFromDNSKey(target
, zsk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3456 kskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(ksk
, kskds
);
3457 zskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(zsk
, zskds
);
3459 /* Set the root DS */
3460 auto luaconfsCopy
= g_luaconfs
.getCopy();
3461 luaconfsCopy
.dsAnchors
.clear();
3462 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(kskds
);
3463 g_luaconfs
.setState(luaconfsCopy
);
3465 size_t queriesCount
= 0;
3467 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
) {
3470 if (domain
== target
&& type
== QType::NS
) {
3472 setLWResult(res
, 0, true, false, true);
3473 char addr
[] = "a.root-servers.net.";
3474 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3476 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3479 addRRSIG(zskeys
, res
->d_records
, domain
, 300);
3481 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3482 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3485 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3487 setLWResult(res
, 0, true, false, true);
3489 addDNSKEY(kskeys
, domain
, 300, res
->d_records
);
3490 addDNSKEY(zskeys
, domain
, 300, res
->d_records
);
3491 addRRSIG(kskeys
, 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(), Secure
);
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(), Secure
);
3512 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3513 BOOST_CHECK_EQUAL(queriesCount
, 2);
3516 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey
) {
3517 std::unique_ptr
<SyncRes
> sr
;
3520 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3523 const DNSName
target(".");
3526 auto luaconfsCopy
= g_luaconfs
.getCopy();
3527 luaconfsCopy
.dsAnchors
.clear();
3528 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3529 g_luaconfs
.setState(luaconfsCopy
);
3531 size_t queriesCount
= 0;
3533 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
) {
3536 if (domain
== target
&& type
== QType::NS
) {
3538 setLWResult(res
, 0, true, false, true);
3539 char addr
[] = "a.root-servers.net.";
3540 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3542 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3545 addRRSIG(keys
, res
->d_records
, domain
, 300);
3547 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3548 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3551 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3553 setLWResult(res
, 0, true, false, true);
3563 vector
<DNSRecord
> ret
;
3564 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3565 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3566 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3567 /* 13 NS + 1 RRSIG */
3568 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3569 BOOST_CHECK_EQUAL(queriesCount
, 2);
3571 /* again, to test the cache */
3573 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3574 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3575 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3576 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3577 BOOST_CHECK_EQUAL(queriesCount
, 2);
3580 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds
) {
3581 std::unique_ptr
<SyncRes
> sr
;
3584 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3587 const DNSName
target(".");
3588 testkeysset_t dskeys
;
3591 /* Generate key material for "." */
3592 auto dckeDS
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3593 dckeDS
->create(dckeDS
->getBits());
3594 DNSSECPrivateKey dskey
;
3595 dskey
.d_flags
= 257;
3596 dskey
.setKey(dckeDS
);
3597 DSRecordContent drc
= makeDSFromDNSKey(target
, dskey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3599 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3600 dcke
->create(dcke
->getBits());
3601 DNSSECPrivateKey dpk
;
3604 DSRecordContent uselessdrc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3606 dskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dskey
, drc
);
3607 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, uselessdrc
);
3609 /* Set the root DS */
3610 auto luaconfsCopy
= g_luaconfs
.getCopy();
3611 luaconfsCopy
.dsAnchors
.clear();
3612 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3613 g_luaconfs
.setState(luaconfsCopy
);
3615 size_t queriesCount
= 0;
3617 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
) {
3620 if (domain
== target
&& type
== QType::NS
) {
3622 setLWResult(res
, 0, true, false, true);
3623 char addr
[] = "a.root-servers.net.";
3624 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3626 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3629 addRRSIG(keys
, res
->d_records
, domain
, 300);
3631 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3632 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3635 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3637 setLWResult(res
, 0, true, false, true);
3639 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3640 addRRSIG(keys
, res
->d_records
, domain
, 300);
3648 vector
<DNSRecord
> ret
;
3649 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3650 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3651 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3652 /* 13 NS + 1 RRSIG */
3653 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3654 BOOST_CHECK_EQUAL(queriesCount
, 2);
3656 /* again, to test the cache */
3658 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3659 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3660 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3661 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3662 BOOST_CHECK_EQUAL(queriesCount
, 2);
3665 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey
) {
3666 std::unique_ptr
<SyncRes
> sr
;
3669 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3672 const DNSName
target(".");
3674 testkeysset_t rrsigkeys
;
3676 auto luaconfsCopy
= g_luaconfs
.getCopy();
3677 luaconfsCopy
.dsAnchors
.clear();
3678 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3679 g_luaconfs
.setState(luaconfsCopy
);
3681 auto dckeRRSIG
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3682 dckeRRSIG
->create(dckeRRSIG
->getBits());
3683 DNSSECPrivateKey rrsigkey
;
3684 rrsigkey
.d_flags
= 257;
3685 rrsigkey
.setKey(dckeRRSIG
);
3686 DSRecordContent rrsigds
= makeDSFromDNSKey(target
, rrsigkey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3688 rrsigkeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(rrsigkey
, rrsigds
);
3690 size_t queriesCount
= 0;
3692 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
) {
3695 if (domain
== target
&& type
== QType::NS
) {
3697 setLWResult(res
, 0, true, false, true);
3698 char addr
[] = "a.root-servers.net.";
3699 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3701 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3704 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3706 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3707 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3710 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3712 setLWResult(res
, 0, true, false, true);
3714 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3715 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3723 vector
<DNSRecord
> ret
;
3724 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3725 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3726 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3727 /* 13 NS + 1 RRSIG */
3728 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3729 BOOST_CHECK_EQUAL(queriesCount
, 2);
3731 /* again, to test the cache */
3733 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3734 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3735 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3736 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3737 BOOST_CHECK_EQUAL(queriesCount
, 2);
3740 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig
) {
3741 std::unique_ptr
<SyncRes
> sr
;
3744 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3747 const DNSName
target(".");
3750 auto luaconfsCopy
= g_luaconfs
.getCopy();
3751 luaconfsCopy
.dsAnchors
.clear();
3752 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3753 g_luaconfs
.setState(luaconfsCopy
);
3755 size_t queriesCount
= 0;
3757 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
) {
3760 if (domain
== target
&& type
== QType::NS
) {
3762 setLWResult(res
, 0, true, false, true);
3763 char addr
[] = "a.root-servers.net.";
3764 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3766 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3771 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3772 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3775 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3777 setLWResult(res
, 0, true, false, true);
3779 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3780 addRRSIG(keys
, res
->d_records
, domain
, 300);
3788 vector
<DNSRecord
> ret
;
3789 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3790 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3791 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3792 /* 13 NS + 0 RRSIG */
3793 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3794 /* no RRSIG so no query for DNSKEYs */
3795 BOOST_CHECK_EQUAL(queriesCount
, 1);
3797 /* again, to test the cache */
3799 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3800 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3801 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3802 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3803 BOOST_CHECK_EQUAL(queriesCount
, 1);
3806 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm
) {
3807 std::unique_ptr
<SyncRes
> sr
;
3810 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3813 const DNSName
target(".");
3816 /* Generate key material for "." */
3817 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3818 dcke
->create(dcke
->getBits());
3819 DNSSECPrivateKey dpk
;
3822 /* Fake algorithm number (private) */
3823 dpk
.d_algorithm
= 253;
3825 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3826 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, drc
);
3827 /* Fake algorithm number (private) */
3828 drc
.d_algorithm
= 253;
3830 /* Set the root DS */
3831 auto luaconfsCopy
= g_luaconfs
.getCopy();
3832 luaconfsCopy
.dsAnchors
.clear();
3833 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3834 g_luaconfs
.setState(luaconfsCopy
);
3836 size_t queriesCount
= 0;
3838 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
) {
3841 if (domain
== target
&& type
== QType::NS
) {
3843 setLWResult(res
, 0, true, false, true);
3844 char addr
[] = "a.root-servers.net.";
3845 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3847 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3850 addRRSIG(keys
, res
->d_records
, domain
, 300);
3852 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3853 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3856 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3858 setLWResult(res
, 0, true, false, true);
3860 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3861 addRRSIG(keys
, res
->d_records
, domain
, 300);
3869 vector
<DNSRecord
> ret
;
3870 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3871 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3872 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3873 /* 13 NS + 1 RRSIG */
3874 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3875 /* no supported DS so no query for DNSKEYs */
3876 BOOST_CHECK_EQUAL(queriesCount
, 1);
3878 /* again, to test the cache */
3880 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3881 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3882 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3883 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3884 BOOST_CHECK_EQUAL(queriesCount
, 1);
3887 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest
) {
3888 std::unique_ptr
<SyncRes
> sr
;
3891 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3894 const DNSName
target(".");
3897 /* Generate key material for "." */
3898 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3899 dcke
->create(dcke
->getBits());
3900 DNSSECPrivateKey dpk
;
3903 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3904 /* Fake digest number (reserved) */
3905 drc
.d_digesttype
= 0;
3907 keys
[target
] = std::pair
<DNSSECPrivateKey
, DSRecordContent
>(dpk
, drc
);
3909 /* Set the root DS */
3910 auto luaconfsCopy
= g_luaconfs
.getCopy();
3911 luaconfsCopy
.dsAnchors
.clear();
3912 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3913 g_luaconfs
.setState(luaconfsCopy
);
3915 size_t queriesCount
= 0;
3917 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
) {
3920 if (domain
== target
&& type
== QType::NS
) {
3922 setLWResult(res
, 0, true, false, true);
3923 char addr
[] = "a.root-servers.net.";
3924 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3926 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3929 addRRSIG(keys
, res
->d_records
, domain
, 300);
3931 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3932 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3935 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3937 setLWResult(res
, 0, true, false, true);
3939 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3940 addRRSIG(keys
, res
->d_records
, domain
, 300);
3948 vector
<DNSRecord
> ret
;
3949 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3950 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3951 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3952 /* 13 NS + 1 RRSIG */
3953 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3954 /* no supported DS so no query for DNSKEYs */
3955 BOOST_CHECK_EQUAL(queriesCount
, 1);
3957 /* again, to test the cache */
3959 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3960 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3961 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
3962 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3963 BOOST_CHECK_EQUAL(queriesCount
, 1);
3966 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig
) {
3967 std::unique_ptr
<SyncRes
> sr
;
3970 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3973 const DNSName
target(".");
3976 auto luaconfsCopy
= g_luaconfs
.getCopy();
3977 luaconfsCopy
.dsAnchors
.clear();
3978 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
3980 g_luaconfs
.setState(luaconfsCopy
);
3982 size_t queriesCount
= 0;
3984 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
) {
3987 if (domain
== target
&& type
== QType::NS
) {
3989 setLWResult(res
, 0, true, false, true);
3990 char addr
[] = "a.root-servers.net.";
3991 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3993 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3996 addRRSIG(keys
, res
->d_records
, domain
, 300, true);
3998 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3999 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4002 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4004 setLWResult(res
, 0, true, false, true);
4006 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4007 addRRSIG(keys
, res
->d_records
, domain
, 300);
4015 vector
<DNSRecord
> ret
;
4016 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4017 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4018 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4019 /* 13 NS + 1 RRSIG */
4020 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4021 BOOST_CHECK_EQUAL(queriesCount
, 2);
4023 /* again, to test the cache */
4025 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4026 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4027 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4028 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4029 BOOST_CHECK_EQUAL(queriesCount
, 2);
4032 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo
) {
4033 std::unique_ptr
<SyncRes
> sr
;
4036 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4039 const DNSName
target(".");
4042 auto luaconfsCopy
= g_luaconfs
.getCopy();
4043 luaconfsCopy
.dsAnchors
.clear();
4044 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4046 g_luaconfs
.setState(luaconfsCopy
);
4048 size_t queriesCount
= 0;
4050 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
) {
4053 if (domain
== target
&& type
== QType::NS
) {
4055 setLWResult(res
, 0, true, false, true);
4056 char addr
[] = "a.root-servers.net.";
4057 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4059 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4062 /* FORCE WRONG ALGO */
4063 addRRSIG(keys
, res
->d_records
, domain
, 300, false, DNSSECKeeper::RSASHA256
);
4065 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4066 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4069 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4071 setLWResult(res
, 0, true, false, true);
4073 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4074 addRRSIG(keys
, res
->d_records
, domain
, 300);
4082 vector
<DNSRecord
> ret
;
4083 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4084 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4085 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4086 /* 13 NS + 1 RRSIG */
4087 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4088 BOOST_CHECK_EQUAL(queriesCount
, 2);
4090 /* again, to test the cache */
4092 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4093 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4094 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4095 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4096 BOOST_CHECK_EQUAL(queriesCount
, 2);
4099 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos
) {
4100 std::unique_ptr
<SyncRes
> sr
;
4103 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4106 const DNSName
target("powerdns.com.");
4107 const ComboAddress
targetAddr("192.0.2.42");
4110 auto luaconfsCopy
= g_luaconfs
.getCopy();
4111 luaconfsCopy
.dsAnchors
.clear();
4112 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4113 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4114 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384
, DNSSECKeeper::SHA384
, keys
);
4116 g_luaconfs
.setState(luaconfsCopy
);
4118 size_t queriesCount
= 0;
4120 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
) {
4123 DNSName auth
= domain
;
4124 if (domain
== target
) {
4125 auth
= DNSName("powerdns.com.");
4128 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4129 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4132 if (isRootServer(ip
)) {
4133 setLWResult(res
, 0, false, false, true);
4134 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4135 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4136 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4137 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4141 if (ip
== ComboAddress("192.0.2.1:53")) {
4142 if (domain
== DNSName("com.")) {
4143 setLWResult(res
, 0, true, false, true);
4144 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4145 addRRSIG(keys
, res
->d_records
, domain
, 300);
4146 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4147 addRRSIG(keys
, res
->d_records
, domain
, 300);
4150 setLWResult(res
, 0, false, false, true);
4151 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4152 addDS(auth
, 300, res
->d_records
, keys
);
4153 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4154 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4159 if (ip
== ComboAddress("192.0.2.2:53")) {
4160 if (type
== QType::NS
) {
4161 setLWResult(res
, 0, true, false, true);
4162 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4163 addRRSIG(keys
, res
->d_records
, auth
, 300);
4164 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4165 addRRSIG(keys
, res
->d_records
, auth
, 300);
4168 setLWResult(res
, RCode::NoError
, true, false, true);
4169 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4170 addRRSIG(keys
, res
->d_records
, auth
, 300);
4178 vector
<DNSRecord
> ret
;
4179 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4180 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4181 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4182 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4183 BOOST_CHECK_EQUAL(queriesCount
, 8);
4185 /* again, to test the cache */
4187 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4188 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4189 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4190 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4191 BOOST_CHECK_EQUAL(queriesCount
, 8);
4194 BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns
) {
4195 std::unique_ptr
<SyncRes
> sr
;
4198 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4201 const DNSName
target("powerdns.com.");
4202 const ComboAddress
targetAddr("192.0.2.42");
4205 auto luaconfsCopy
= g_luaconfs
.getCopy();
4206 luaconfsCopy
.dsAnchors
.clear();
4207 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4208 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4209 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4210 g_luaconfs
.setState(luaconfsCopy
);
4212 size_t queriesCount
= 0;
4214 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
) {
4217 DNSName auth
= domain
;
4218 if (domain
== target
) {
4219 auth
= DNSName("powerdns.com.");
4222 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4223 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4226 if (isRootServer(ip
)) {
4227 setLWResult(res
, 0, false, false, true);
4228 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4229 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4230 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4231 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4235 if (ip
== ComboAddress("192.0.2.1:53")) {
4236 if (domain
== DNSName("com.")) {
4237 setLWResult(res
, 0, true, false, true);
4238 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4239 addRRSIG(keys
, res
->d_records
, domain
, 300);
4240 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4241 addRRSIG(keys
, res
->d_records
, domain
, 300);
4244 setLWResult(res
, 0, false, false, true);
4245 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4246 addDS(auth
, 300, res
->d_records
, keys
);
4247 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4248 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4253 if (ip
== ComboAddress("192.0.2.2:53")) {
4254 if (type
== QType::NS
) {
4255 setLWResult(res
, 0, true, false, true);
4256 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4257 addRRSIG(keys
, res
->d_records
, auth
, 300);
4258 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4259 addRRSIG(keys
, res
->d_records
, auth
, 300);
4262 setLWResult(res
, RCode::NoError
, true, false, true);
4263 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4264 addRRSIG(keys
, res
->d_records
, auth
, 300);
4272 vector
<DNSRecord
> ret
;
4273 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4274 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4275 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4276 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4277 BOOST_CHECK_EQUAL(queriesCount
, 8);
4279 /* again, to test the cache */
4281 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4282 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4283 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4284 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4285 BOOST_CHECK_EQUAL(queriesCount
, 8);
4287 /* this time we ask for the NS that should be in the cache, to check
4288 the validation status */
4290 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4291 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4292 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4293 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4294 BOOST_CHECK_EQUAL(queriesCount
, 9);
4298 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns
) {
4299 std::unique_ptr
<SyncRes
> sr
;
4302 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4305 const DNSName
target("powerdns.com.");
4306 const ComboAddress
targetAddr("192.0.2.42");
4309 auto luaconfsCopy
= g_luaconfs
.getCopy();
4310 luaconfsCopy
.dsAnchors
.clear();
4311 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4312 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4313 g_luaconfs
.setState(luaconfsCopy
);
4315 size_t queriesCount
= 0;
4317 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
) {
4320 DNSName auth
= domain
;
4321 if (domain
== target
) {
4322 auth
= DNSName("powerdns.com.");
4325 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4326 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4329 if (isRootServer(ip
)) {
4330 setLWResult(res
, 0, false, false, true);
4331 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4332 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4333 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4334 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4338 if (ip
== ComboAddress("192.0.2.1:53")) {
4339 if (domain
== DNSName("com.")) {
4340 setLWResult(res
, 0, true, false, true);
4341 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4342 addRRSIG(keys
, res
->d_records
, domain
, 300);
4343 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4344 addRRSIG(keys
, res
->d_records
, domain
, 300);
4347 setLWResult(res
, 0, false, false, true);
4348 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4350 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
4351 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4352 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4357 if (ip
== ComboAddress("192.0.2.2:53")) {
4358 if (type
== QType::NS
) {
4359 setLWResult(res
, 0, true, false, true);
4360 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4361 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4364 setLWResult(res
, RCode::NoError
, true, false, true);
4365 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4373 vector
<DNSRecord
> ret
;
4374 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4375 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4376 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4377 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4378 BOOST_CHECK_EQUAL(queriesCount
, 7);
4380 /* again, to test the cache */
4382 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4383 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4384 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4385 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4386 BOOST_CHECK_EQUAL(queriesCount
, 7);
4388 /* this time we ask for the NS that should be in the cache, to check
4389 the validation status */
4391 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4392 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4393 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4394 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4395 BOOST_CHECK_EQUAL(queriesCount
, 8);
4398 BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta
) {
4399 std::unique_ptr
<SyncRes
> sr
;
4402 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4405 const DNSName
target("powerdns.com.");
4406 const ComboAddress
targetAddr("192.0.2.42");
4409 auto luaconfsCopy
= g_luaconfs
.getCopy();
4410 luaconfsCopy
.dsAnchors
.clear();
4411 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4412 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4413 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4415 /* Add a NTA for "powerdns.com" */
4416 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4418 g_luaconfs
.setState(luaconfsCopy
);
4420 size_t queriesCount
= 0;
4422 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
) {
4425 DNSName auth
= domain
;
4426 if (domain
== target
) {
4427 auth
= DNSName("powerdns.com.");
4430 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4431 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4434 if (isRootServer(ip
)) {
4435 setLWResult(res
, 0, false, false, true);
4436 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4437 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4438 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4439 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4443 if (ip
== ComboAddress("192.0.2.1:53")) {
4444 if (domain
== DNSName("com.")) {
4445 setLWResult(res
, 0, true, false, true);
4446 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4447 addRRSIG(keys
, res
->d_records
, domain
, 300);
4448 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4449 addRRSIG(keys
, res
->d_records
, domain
, 300);
4452 setLWResult(res
, 0, false, false, true);
4453 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4454 addDS(auth
, 300, res
->d_records
, keys
);
4455 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4456 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4461 if (ip
== ComboAddress("192.0.2.2:53")) {
4462 if (type
== QType::NS
) {
4463 setLWResult(res
, 0, true, false, true);
4464 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4465 addRRSIG(keys
, res
->d_records
, auth
, 300);
4466 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4467 addRRSIG(keys
, res
->d_records
, auth
, 300);
4470 setLWResult(res
, RCode::NoError
, true, false, true);
4471 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4472 addRRSIG(keys
, res
->d_records
, auth
, 300);
4480 vector
<DNSRecord
> ret
;
4481 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4482 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4483 /* Should be insecure because of the NTA */
4484 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4485 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4486 BOOST_CHECK_EQUAL(queriesCount
, 5);
4488 /* again, to test the cache */
4490 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4491 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4492 /* Should be insecure because of the NTA */
4493 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4494 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4495 BOOST_CHECK_EQUAL(queriesCount
, 5);
4498 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta
) {
4499 std::unique_ptr
<SyncRes
> sr
;
4502 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4505 const DNSName
target("powerdns.com.");
4506 const ComboAddress
targetAddr("192.0.2.42");
4509 auto luaconfsCopy
= g_luaconfs
.getCopy();
4510 luaconfsCopy
.dsAnchors
.clear();
4511 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4512 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4513 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4515 /* Add a NTA for "powerdns.com" */
4516 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4518 g_luaconfs
.setState(luaconfsCopy
);
4520 size_t queriesCount
= 0;
4522 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
) {
4525 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4526 setLWResult(res
, 0, false, false, true);
4527 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4531 if (isRootServer(ip
)) {
4532 setLWResult(res
, 0, false, false, true);
4533 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4534 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4537 else if (ip
== ComboAddress("192.0.2.1:53")) {
4538 if (domain
== DNSName("com.")) {
4539 setLWResult(res
, 0, true, false, true);
4540 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4541 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4544 setLWResult(res
, 0, false, false, true);
4545 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4546 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4550 else if (ip
== ComboAddress("192.0.2.2:53")) {
4551 if (type
== QType::NS
) {
4552 setLWResult(res
, 0, true, false, true);
4553 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4554 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4557 setLWResult(res
, RCode::NoError
, true, false, true);
4558 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4567 /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
4568 vector
<DNSRecord
> ret
;
4569 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4570 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4571 /* Should be insecure because of the NTA */
4572 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4573 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4574 BOOST_CHECK_EQUAL(queriesCount
, 4);
4576 /* again, to test the cache */
4578 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4579 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4580 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4581 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4582 BOOST_CHECK_EQUAL(queriesCount
, 4);
4585 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec
) {
4586 std::unique_ptr
<SyncRes
> sr
;
4589 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4592 const DNSName
target("powerdns.com.");
4595 auto luaconfsCopy
= g_luaconfs
.getCopy();
4596 luaconfsCopy
.dsAnchors
.clear();
4597 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4598 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4599 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4601 g_luaconfs
.setState(luaconfsCopy
);
4603 size_t queriesCount
= 0;
4605 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
) {
4608 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4609 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
4612 if (isRootServer(ip
)) {
4613 setLWResult(res
, 0, false, false, true);
4614 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4615 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4616 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4617 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4620 else if (ip
== ComboAddress("192.0.2.1:53")) {
4621 if (domain
== DNSName("com.")) {
4622 setLWResult(res
, 0, true, false, true);
4623 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4624 addRRSIG(keys
, res
->d_records
, domain
, 300);
4625 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4626 addRRSIG(keys
, res
->d_records
, domain
, 300);
4629 setLWResult(res
, 0, false, false, true);
4630 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4631 addDS(domain
, 300, res
->d_records
, keys
);
4632 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4633 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4637 else if (ip
== ComboAddress("192.0.2.2:53")) {
4638 if (type
== QType::NS
) {
4639 setLWResult(res
, 0, true, false, true);
4640 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4641 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4642 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4643 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4646 setLWResult(res
, 0, true, false, true);
4647 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4648 addRRSIG(keys
, res
->d_records
, domain
, 300);
4649 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
4650 addRRSIG(keys
, res
->d_records
, domain
, 300);
4659 vector
<DNSRecord
> ret
;
4660 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4661 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4662 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4663 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4664 BOOST_CHECK_EQUAL(queriesCount
, 8);
4666 /* again, to test the cache */
4668 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4669 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4670 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4671 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4672 BOOST_CHECK_EQUAL(queriesCount
, 8);
4675 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec
) {
4676 std::unique_ptr
<SyncRes
> sr
;
4679 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4682 const DNSName
target("nx.powerdns.com.");
4685 auto luaconfsCopy
= g_luaconfs
.getCopy();
4686 luaconfsCopy
.dsAnchors
.clear();
4687 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4688 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4689 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4691 g_luaconfs
.setState(luaconfsCopy
);
4693 size_t queriesCount
= 0;
4695 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
) {
4698 DNSName auth
= domain
;
4699 if (domain
== target
) {
4700 auth
= DNSName("powerdns.com.");
4702 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4703 if (type
== QType::DS
&& domain
== target
) {
4704 setLWResult(res
, RCode::NXDomain
, true, false, true);
4705 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4706 addRRSIG(keys
, res
->d_records
, auth
, 300);
4707 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4708 addRRSIG(keys
, res
->d_records
, auth
, 300);
4712 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4716 if (isRootServer(ip
)) {
4717 setLWResult(res
, 0, false, false, true);
4718 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4719 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4720 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4721 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4724 else if (ip
== ComboAddress("192.0.2.1:53")) {
4725 if (domain
== DNSName("com.")) {
4726 setLWResult(res
, 0, true, false, true);
4727 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4728 addRRSIG(keys
, res
->d_records
, domain
, 300);
4729 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4730 addRRSIG(keys
, res
->d_records
, domain
, 300);
4733 setLWResult(res
, 0, false, false, true);
4734 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4735 addDS(auth
, 300, res
->d_records
, keys
);
4736 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4737 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4741 else if (ip
== ComboAddress("192.0.2.2:53")) {
4742 if (type
== QType::NS
) {
4743 setLWResult(res
, 0, true, false, true);
4744 if (domain
== DNSName("powerdns.com.")) {
4745 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4746 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4747 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4748 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4751 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4752 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4753 addNSECRecordToLW(DNSName("nx.powerdns.com."), DNSName("nz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4754 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4758 setLWResult(res
, RCode::NXDomain
, true, false, true);
4759 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4760 addRRSIG(keys
, res
->d_records
, auth
, 300);
4761 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4762 addRRSIG(keys
, res
->d_records
, auth
, 300);
4763 /* add wildcard denial */
4764 addNSECRecordToLW(DNSName("powerdns.com."), DNSName("a.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4765 addRRSIG(keys
, res
->d_records
, auth
, 300);
4774 vector
<DNSRecord
> ret
;
4775 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4776 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
4777 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4778 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
4779 BOOST_CHECK_EQUAL(queriesCount
, 9);
4781 /* again, to test the cache */
4783 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4784 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
4785 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4786 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
4787 BOOST_CHECK_EQUAL(queriesCount
, 9);
4790 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard
) {
4791 std::unique_ptr
<SyncRes
> sr
;
4794 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4797 const DNSName
target("www.powerdns.com.");
4800 auto luaconfsCopy
= g_luaconfs
.getCopy();
4801 luaconfsCopy
.dsAnchors
.clear();
4802 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4803 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4804 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4806 g_luaconfs
.setState(luaconfsCopy
);
4808 size_t queriesCount
= 0;
4810 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
) {
4813 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4814 if (type
== QType::DS
&& domain
== target
) {
4815 setLWResult(res
, RCode::NoError
, true, false, true);
4816 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4817 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
4818 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4819 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4823 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
4827 if (isRootServer(ip
)) {
4828 setLWResult(res
, 0, false, false, true);
4829 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4830 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4831 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4832 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4835 else if (ip
== ComboAddress("192.0.2.1:53")) {
4836 if (domain
== DNSName("com.")) {
4837 setLWResult(res
, 0, true, false, true);
4838 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4839 addRRSIG(keys
, res
->d_records
, domain
, 300);
4840 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4841 addRRSIG(keys
, res
->d_records
, domain
, 300);
4844 setLWResult(res
, 0, false, false, true);
4845 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4846 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
4847 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4848 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4852 else if (ip
== ComboAddress("192.0.2.2:53")) {
4853 setLWResult(res
, 0, true, false, true);
4854 if (type
== QType::NS
) {
4855 if (domain
== DNSName("powerdns.com.")) {
4856 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4857 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4858 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4859 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4862 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4863 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4864 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4865 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4869 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
4870 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
4871 /* we need to add the proof that this name does not exist, so the wildcard may apply */
4872 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4873 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4882 vector
<DNSRecord
> ret
;
4883 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4884 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4885 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4886 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4887 BOOST_CHECK_EQUAL(queriesCount
, 9);
4889 /* again, to test the cache */
4891 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4892 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4893 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4894 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4895 BOOST_CHECK_EQUAL(queriesCount
, 9);
4898 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_nodata_nowildcard
) {
4899 std::unique_ptr
<SyncRes
> sr
;
4902 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4905 const DNSName
target("www.com.");
4908 auto luaconfsCopy
= g_luaconfs
.getCopy();
4909 luaconfsCopy
.dsAnchors
.clear();
4910 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4911 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4913 g_luaconfs
.setState(luaconfsCopy
);
4915 size_t queriesCount
= 0;
4917 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
) {
4920 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4921 if (type
== QType::DS
&& domain
== target
) {
4922 DNSName
auth("com.");
4923 setLWResult(res
, 0, true, false, true);
4925 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
4926 addRRSIG(keys
, res
->d_records
, auth
, 300);
4927 /* add a NSEC denying the DS AND the existence of a cut (no NS) */
4928 addNSECRecordToLW(domain
, DNSName("z") + domain
, { QType::NSEC
}, 600, res
->d_records
);
4929 addRRSIG(keys
, res
->d_records
, auth
, 300);
4932 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
4935 if (isRootServer(ip
)) {
4936 setLWResult(res
, 0, false, false, true);
4937 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4938 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4939 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4940 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4943 else if (ip
== ComboAddress("192.0.2.1:53")) {
4944 setLWResult(res
, 0, true, false, true);
4946 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4947 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4948 /* no record for this name */
4949 addNSECRecordToLW(DNSName("wwv.com."), DNSName("wwx.com."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4950 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4951 /* a wildcard matches but has no record for this type */
4952 addNSECRecordToLW(DNSName("*.com."), DNSName("com."), { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4953 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
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(), Secure
);
4965 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
4966 BOOST_CHECK_EQUAL(queriesCount
, 6);
4968 /* again, to test the cache */
4970 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4971 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4972 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4973 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
4974 BOOST_CHECK_EQUAL(queriesCount
, 6);
4977 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard
) {
4978 std::unique_ptr
<SyncRes
> sr
;
4981 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4984 const DNSName
target("www.com.");
4987 auto luaconfsCopy
= g_luaconfs
.getCopy();
4988 luaconfsCopy
.dsAnchors
.clear();
4989 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4990 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4992 g_luaconfs
.setState(luaconfsCopy
);
4994 size_t queriesCount
= 0;
4996 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
) {
4999 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5000 if (type
== QType::DS
&& domain
== target
) {
5001 DNSName
auth("com.");
5002 setLWResult(res
, 0, true, false, true);
5004 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5005 addRRSIG(keys
, res
->d_records
, auth
, 300);
5006 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5007 /* first the closest encloser */
5008 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5009 addRRSIG(keys
, res
->d_records
, auth
, 300);
5010 /* then the next closer */
5011 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5012 addRRSIG(keys
, res
->d_records
, auth
, 300);
5013 /* a wildcard matches but has no record for this type */
5014 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5015 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5018 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5021 if (isRootServer(ip
)) {
5022 setLWResult(res
, 0, false, false, true);
5023 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5024 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5025 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5026 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5029 else if (ip
== ComboAddress("192.0.2.1:53")) {
5030 setLWResult(res
, 0, true, false, true);
5032 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5033 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5034 /* no record for this name */
5035 /* first the closest encloser */
5036 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5037 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5038 /* then the next closer */
5039 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5040 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5041 /* a wildcard matches but has no record for this type */
5042 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5043 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5051 vector
<DNSRecord
> ret
;
5052 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5053 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5054 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5055 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5056 BOOST_CHECK_EQUAL(queriesCount
, 6);
5058 /* again, to test the cache */
5060 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5061 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5062 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5063 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5064 BOOST_CHECK_EQUAL(queriesCount
, 6);
5067 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_too_many_iterations
) {
5068 std::unique_ptr
<SyncRes
> sr
;
5071 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5074 const DNSName
target("www.com.");
5077 auto luaconfsCopy
= g_luaconfs
.getCopy();
5078 luaconfsCopy
.dsAnchors
.clear();
5079 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5080 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5082 g_luaconfs
.setState(luaconfsCopy
);
5084 size_t queriesCount
= 0;
5086 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
) {
5089 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5090 if (type
== QType::DS
&& domain
== target
) {
5091 DNSName
auth("com.");
5092 setLWResult(res
, 0, true, false, true);
5094 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5095 addRRSIG(keys
, res
->d_records
, auth
, 300);
5096 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5097 /* first the closest encloser */
5098 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5099 addRRSIG(keys
, res
->d_records
, auth
, 300);
5100 /* then the next closer */
5101 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5102 addRRSIG(keys
, res
->d_records
, auth
, 300);
5103 /* a wildcard matches but has no record for this type */
5104 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5105 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5108 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5111 if (isRootServer(ip
)) {
5112 setLWResult(res
, 0, false, false, true);
5113 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5114 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5115 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5116 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5119 else if (ip
== ComboAddress("192.0.2.1:53")) {
5120 setLWResult(res
, 0, true, false, true);
5122 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5123 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5124 /* no record for this name */
5125 /* first the closest encloser */
5126 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5127 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5128 /* then the next closer */
5129 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5130 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5131 /* a wildcard matches but has no record for this type */
5132 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5133 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5141 /* we are generating NSEC3 with more iterations than we allow, so we should go Insecure */
5142 vector
<DNSRecord
> ret
;
5143 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5144 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5145 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5146 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5147 BOOST_CHECK_EQUAL(queriesCount
, 6);
5149 /* again, to test the cache */
5151 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5152 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5153 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5154 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5155 BOOST_CHECK_EQUAL(queriesCount
, 6);
5158 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard
) {
5159 std::unique_ptr
<SyncRes
> sr
;
5162 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5165 const DNSName
target("www.powerdns.com.");
5168 auto luaconfsCopy
= g_luaconfs
.getCopy();
5169 luaconfsCopy
.dsAnchors
.clear();
5170 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5171 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5172 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5174 g_luaconfs
.setState(luaconfsCopy
);
5176 size_t queriesCount
= 0;
5178 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
) {
5181 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5182 if (type
== QType::DS
&& domain
== target
) {
5183 setLWResult(res
, RCode::NoError
, true, false, true);
5184 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5185 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5186 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5187 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5191 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5195 if (isRootServer(ip
)) {
5196 setLWResult(res
, 0, false, false, true);
5197 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5198 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5199 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5200 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5203 else if (ip
== ComboAddress("192.0.2.1:53")) {
5204 if (domain
== DNSName("com.")) {
5205 setLWResult(res
, 0, true, false, true);
5206 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5207 addRRSIG(keys
, res
->d_records
, domain
, 300);
5208 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5209 addRRSIG(keys
, res
->d_records
, domain
, 300);
5212 setLWResult(res
, 0, false, false, true);
5213 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5214 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5215 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5216 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5220 else if (ip
== ComboAddress("192.0.2.2:53")) {
5221 setLWResult(res
, 0, true, false, true);
5222 if (type
== QType::NS
) {
5223 if (domain
== DNSName("powerdns.com.")) {
5224 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5225 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5226 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5227 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5230 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5231 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5232 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5233 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5237 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5238 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5239 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5240 /* first the closest encloser */
5241 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5242 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5243 /* then the next closer */
5244 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5245 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5254 vector
<DNSRecord
> ret
;
5255 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5256 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5257 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5258 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5259 BOOST_CHECK_EQUAL(queriesCount
, 9);
5261 /* again, to test the cache */
5263 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5264 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5265 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5266 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5267 BOOST_CHECK_EQUAL(queriesCount
, 9);
5270 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard_too_many_iterations
) {
5271 std::unique_ptr
<SyncRes
> sr
;
5274 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5277 const DNSName
target("www.powerdns.com.");
5280 auto luaconfsCopy
= g_luaconfs
.getCopy();
5281 luaconfsCopy
.dsAnchors
.clear();
5282 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5283 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5284 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5286 g_luaconfs
.setState(luaconfsCopy
);
5288 size_t queriesCount
= 0;
5290 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
) {
5293 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5294 if (type
== QType::DS
&& domain
== target
) {
5295 setLWResult(res
, RCode::NoError
, true, false, true);
5296 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5297 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5298 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5299 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5303 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5307 if (isRootServer(ip
)) {
5308 setLWResult(res
, 0, false, false, true);
5309 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5310 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5311 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5312 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5315 else if (ip
== ComboAddress("192.0.2.1:53")) {
5316 if (domain
== DNSName("com.")) {
5317 setLWResult(res
, 0, true, false, true);
5318 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5319 addRRSIG(keys
, res
->d_records
, domain
, 300);
5320 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5321 addRRSIG(keys
, res
->d_records
, domain
, 300);
5324 setLWResult(res
, 0, false, false, true);
5325 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5326 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5327 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5328 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5332 else if (ip
== ComboAddress("192.0.2.2:53")) {
5333 setLWResult(res
, 0, true, false, true);
5334 if (type
== QType::NS
) {
5335 if (domain
== DNSName("powerdns.com.")) {
5336 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5337 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5338 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5339 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5342 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5343 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5344 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5345 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5349 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5350 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5351 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5352 /* first the closest encloser */
5353 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5354 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5355 /* then the next closer */
5356 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5357 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5366 /* the NSEC3 providing the denial of existence proof for the next closer has too many iterations,
5367 we should end up Insecure */
5368 vector
<DNSRecord
> ret
;
5369 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5370 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5371 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5372 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5373 BOOST_CHECK_EQUAL(queriesCount
, 9);
5375 /* again, to test the cache */
5377 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5378 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5379 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5380 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5381 BOOST_CHECK_EQUAL(queriesCount
, 9);
5384 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_missing
) {
5385 std::unique_ptr
<SyncRes
> sr
;
5388 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5391 const DNSName
target("www.powerdns.com.");
5394 auto luaconfsCopy
= g_luaconfs
.getCopy();
5395 luaconfsCopy
.dsAnchors
.clear();
5396 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5397 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5398 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5400 g_luaconfs
.setState(luaconfsCopy
);
5402 size_t queriesCount
= 0;
5404 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
) {
5407 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5408 if (type
== QType::DS
&& domain
== target
) {
5409 setLWResult(res
, RCode::NoError
, true, false, true);
5410 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5411 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5412 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5413 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5417 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5421 if (isRootServer(ip
)) {
5422 setLWResult(res
, 0, false, false, true);
5423 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5424 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5425 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5426 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5429 else if (ip
== ComboAddress("192.0.2.1:53")) {
5430 if (domain
== DNSName("com.")) {
5431 setLWResult(res
, 0, true, false, true);
5432 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5433 addRRSIG(keys
, res
->d_records
, domain
, 300);
5434 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5435 addRRSIG(keys
, res
->d_records
, domain
, 300);
5438 setLWResult(res
, 0, false, false, true);
5439 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5440 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5441 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5442 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5446 else if (ip
== ComboAddress("192.0.2.2:53")) {
5447 setLWResult(res
, 0, true, false, true);
5448 if (type
== QType::NS
) {
5449 if (domain
== DNSName("powerdns.com.")) {
5450 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5451 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5452 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5453 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5456 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5457 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5458 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5459 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5463 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5464 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5473 vector
<DNSRecord
> ret
;
5474 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5475 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5476 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5477 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5478 BOOST_CHECK_EQUAL(queriesCount
, 9);
5480 /* again, to test the cache */
5482 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5483 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5484 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5485 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5486 BOOST_CHECK_EQUAL(queriesCount
, 9);
5489 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure
) {
5490 std::unique_ptr
<SyncRes
> sr
;
5493 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5496 const DNSName
target("www.powerdns.com.");
5499 auto luaconfsCopy
= g_luaconfs
.getCopy();
5500 luaconfsCopy
.dsAnchors
.clear();
5501 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5502 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5503 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5505 g_luaconfs
.setState(luaconfsCopy
);
5507 size_t queriesCount
= 0;
5508 size_t dsQueriesCount
= 0;
5510 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
) {
5513 if (type
== QType::DS
) {
5514 DNSName
auth(domain
);
5518 setLWResult(res
, 0, true, false, true);
5519 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5520 addRRSIG(keys
, res
->d_records
, auth
, 300);
5523 else if (type
== QType::DNSKEY
) {
5524 setLWResult(res
, 0, true, false, true);
5525 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5526 addRRSIG(keys
, res
->d_records
, domain
, 300);
5530 if (isRootServer(ip
)) {
5531 setLWResult(res
, 0, false, false, true);
5532 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5533 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5534 /* No DS on referral, and no denial of the DS either */
5537 else if (ip
== ComboAddress("192.0.2.1:53")) {
5538 if (domain
== DNSName("com.")) {
5539 setLWResult(res
, 0, true, false, true);
5540 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5541 addRRSIG(keys
, res
->d_records
, domain
, 300);
5542 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5543 addRRSIG(keys
, res
->d_records
, domain
, 300);
5546 setLWResult(res
, 0, false, false, true);
5547 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5548 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5549 /* No DS on referral, and no denial of the DS either */
5553 else if (ip
== ComboAddress("192.0.2.2:53")) {
5554 setLWResult(res
, 0, true, false, true);
5555 if (type
== QType::NS
) {
5556 if (domain
== DNSName("powerdns.com.")) {
5557 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5558 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5559 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5560 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5563 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5564 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5565 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5566 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5570 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5571 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5581 vector
<DNSRecord
> ret
;
5582 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5583 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5584 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5585 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5586 BOOST_CHECK_EQUAL(queriesCount
, 9);
5587 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5589 /* again, to test the cache */
5591 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5592 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5593 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5594 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5595 BOOST_CHECK_EQUAL(queriesCount
, 9);
5596 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5599 BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop
) {
5600 std::unique_ptr
<SyncRes
> sr
;
5603 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5606 const DNSName
target("www.powerdns.com.");
5609 auto luaconfsCopy
= g_luaconfs
.getCopy();
5610 luaconfsCopy
.dsAnchors
.clear();
5611 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5612 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5613 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5614 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5616 g_luaconfs
.setState(luaconfsCopy
);
5618 size_t queriesCount
= 0;
5620 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
) {
5623 if (type
== QType::DS
) {
5624 DNSName
auth(domain
);
5627 setLWResult(res
, 0, true, false, true);
5628 if (domain
== target
) {
5629 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5630 addRRSIG(keys
, res
->d_records
, target
, 300);
5633 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5634 addRRSIG(keys
, res
->d_records
, auth
, 300);
5638 else if (type
== QType::DNSKEY
) {
5639 setLWResult(res
, 0, true, false, true);
5640 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5641 addRRSIG(keys
, res
->d_records
, domain
, 300);
5645 if (isRootServer(ip
)) {
5646 setLWResult(res
, 0, false, false, true);
5647 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5648 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5649 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5650 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5653 else if (ip
== ComboAddress("192.0.2.1:53")) {
5654 if (domain
== DNSName("com.")) {
5655 setLWResult(res
, 0, true, false, true);
5656 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5657 addRRSIG(keys
, res
->d_records
, domain
, 300);
5658 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5659 addRRSIG(keys
, res
->d_records
, domain
, 300);
5662 setLWResult(res
, 0, false, false, true);
5663 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5665 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5666 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5667 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5671 else if (ip
== ComboAddress("192.0.2.2:53")) {
5672 if (type
== QType::NS
) {
5673 if (domain
== DNSName("powerdns.com.")) {
5674 setLWResult(res
, RCode::Refused
, false, false, true);
5677 setLWResult(res
, 0, true, false, true);
5678 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5679 addRRSIG(keys
, res
->d_records
, domain
, 300);
5680 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5681 addRRSIG(keys
, res
->d_records
, domain
, 300);
5685 setLWResult(res
, 0, true, false, true);
5686 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5687 addRRSIG(keys
, res
->d_records
, DNSName("www.powerdns.com"), 300);
5697 vector
<DNSRecord
> ret
;
5698 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5699 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5700 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5701 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5702 BOOST_CHECK_EQUAL(queriesCount
, 9);
5704 /* again, to test the cache */
5706 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5707 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5708 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5709 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5710 BOOST_CHECK_EQUAL(queriesCount
, 9);
5713 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure
) {
5714 std::unique_ptr
<SyncRes
> sr
;
5717 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5720 const DNSName
target("www.powerdns.com.");
5723 auto luaconfsCopy
= g_luaconfs
.getCopy();
5724 luaconfsCopy
.dsAnchors
.clear();
5725 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5726 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5728 g_luaconfs
.setState(luaconfsCopy
);
5730 size_t queriesCount
= 0;
5731 size_t dsQueriesCount
= 0;
5733 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
) {
5736 if (type
== QType::DS
) {
5737 DNSName
auth(domain
);
5741 setLWResult(res
, 0, true, false, true);
5742 if (domain
== DNSName("com.")) {
5743 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5746 addRecordToLW(res
, "com.", QType::SOA
, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5747 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5748 addNSECRecordToLW(domain
, DNSName("powerdnt.com."), { QType::NS
}, 600, res
->d_records
);
5750 addRRSIG(keys
, res
->d_records
, auth
, 300);
5753 else if (type
== QType::DNSKEY
) {
5754 setLWResult(res
, 0, true, false, true);
5755 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5756 addRRSIG(keys
, res
->d_records
, domain
, 300);
5760 if (isRootServer(ip
)) {
5761 setLWResult(res
, 0, false, false, true);
5762 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5763 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5764 /* No DS on referral, and no denial of the DS either */
5767 else if (ip
== ComboAddress("192.0.2.1:53")) {
5768 if (domain
== DNSName("com.")) {
5769 setLWResult(res
, 0, true, false, true);
5770 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5771 addRRSIG(keys
, res
->d_records
, domain
, 300);
5772 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5773 addRRSIG(keys
, res
->d_records
, domain
, 300);
5776 setLWResult(res
, 0, false, false, true);
5777 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5778 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5779 /* No DS on referral, and no denial of the DS either */
5783 else if (ip
== ComboAddress("192.0.2.2:53")) {
5784 setLWResult(res
, 0, true, false, true);
5785 if (type
== QType::NS
) {
5786 if (domain
== DNSName("powerdns.com.")) {
5787 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5788 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5791 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5795 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5804 vector
<DNSRecord
> ret
;
5805 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5806 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5807 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5808 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5809 BOOST_CHECK_EQUAL(queriesCount
, 7);
5810 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
5812 /* again, to test the cache */
5814 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5815 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5816 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5817 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
5818 BOOST_CHECK_EQUAL(queriesCount
, 7);
5819 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
5822 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec
) {
5823 std::unique_ptr
<SyncRes
> sr
;
5826 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5829 const DNSName
target("powerdns.com.");
5832 auto luaconfsCopy
= g_luaconfs
.getCopy();
5833 luaconfsCopy
.dsAnchors
.clear();
5834 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5835 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5836 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5838 g_luaconfs
.setState(luaconfsCopy
);
5840 size_t queriesCount
= 0;
5842 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
) {
5845 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5846 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5849 if (isRootServer(ip
)) {
5850 setLWResult(res
, 0, false, false, true);
5851 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5852 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5853 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5854 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5857 else if (ip
== ComboAddress("192.0.2.1:53")) {
5858 if (domain
== DNSName("com.")) {
5859 setLWResult(res
, 0, true, false, true);
5860 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
5861 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5862 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5865 setLWResult(res
, 0, false, false, true);
5866 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5867 addDS(domain
, 300, res
->d_records
, keys
);
5868 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5869 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5873 else if (ip
== ComboAddress("192.0.2.2:53")) {
5874 setLWResult(res
, 0, true, false, true);
5875 if (type
== QType::NS
) {
5876 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5877 addRRSIG(keys
, res
->d_records
, domain
, 300);
5880 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5881 addRRSIG(keys
, res
->d_records
, domain
, 300);
5882 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
5883 /* NO RRSIG for the NSEC record! */
5892 /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
5893 vector
<DNSRecord
> ret
;
5894 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5895 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5896 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5897 BOOST_CHECK_EQUAL(ret
.size(), 3);
5898 BOOST_CHECK_EQUAL(queriesCount
, 8);
5900 /* again, to test the cache */
5902 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5903 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5904 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5905 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
5906 BOOST_CHECK_EQUAL(queriesCount
, 8);
5909 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec
) {
5910 std::unique_ptr
<SyncRes
> sr
;
5913 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5916 const DNSName
target("powerdns.com.");
5919 auto luaconfsCopy
= g_luaconfs
.getCopy();
5920 luaconfsCopy
.dsAnchors
.clear();
5921 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5922 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5923 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5925 g_luaconfs
.setState(luaconfsCopy
);
5927 size_t queriesCount
= 0;
5929 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
) {
5932 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5933 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5936 if (isRootServer(ip
)) {
5937 setLWResult(res
, 0, false, false, true);
5938 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5939 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5940 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5941 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5944 else if (ip
== ComboAddress("192.0.2.1:53")) {
5945 if (domain
== DNSName("com.")) {
5946 setLWResult(res
, 0, true, false, true);
5947 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
5948 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5949 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5952 setLWResult(res
, 0, false, false, true);
5953 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5954 addDS(domain
, 300, res
->d_records
, keys
);
5955 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5956 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5960 else if (ip
== ComboAddress("192.0.2.2:53")) {
5961 setLWResult(res
, 0, true, false, true);
5962 if (type
== QType::NS
) {
5963 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5964 addRRSIG(keys
, res
->d_records
, domain
, 300);
5967 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5968 addRRSIG(keys
, res
->d_records
, domain
, 300);
5970 /* NO NSEC record! */
5979 /* no NSEC record in a secure zone, should be Bogus! */
5980 vector
<DNSRecord
> ret
;
5981 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5982 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5983 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5984 BOOST_CHECK_EQUAL(ret
.size(), 2);
5985 BOOST_CHECK_EQUAL(queriesCount
, 8);
5987 /* again, to test the cache */
5989 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5990 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5991 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5992 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5993 BOOST_CHECK_EQUAL(queriesCount
, 8);
5996 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure
) {
5997 std::unique_ptr
<SyncRes
> sr
;
6000 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6003 const DNSName
target("powerdns.com.");
6004 const ComboAddress
targetAddr("192.0.2.42");
6007 auto luaconfsCopy
= g_luaconfs
.getCopy();
6008 luaconfsCopy
.dsAnchors
.clear();
6009 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6010 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6012 g_luaconfs
.setState(luaconfsCopy
);
6014 size_t queriesCount
= 0;
6016 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
) {
6019 if (type
== QType::DS
) {
6020 if (domain
== target
) {
6021 setLWResult(res
, 0, false, false, true);
6022 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6023 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6024 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6027 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6030 else if (type
== QType::DNSKEY
) {
6031 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6032 setLWResult(res
, 0, true, false, true);
6033 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6034 addRRSIG(keys
, res
->d_records
, domain
, 300);
6038 setLWResult(res
, 0, false, false, true);
6039 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6044 if (isRootServer(ip
)) {
6045 setLWResult(res
, 0, false, false, true);
6046 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6047 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6048 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6049 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6052 else if (ip
== ComboAddress("192.0.2.1:53")) {
6053 if (domain
== DNSName("com.")) {
6054 setLWResult(res
, 0, true, false, true);
6055 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6056 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6057 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6060 setLWResult(res
, 0, false, false, true);
6061 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6063 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6064 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6065 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6069 else if (ip
== ComboAddress("192.0.2.2:53")) {
6070 setLWResult(res
, 0, true, false, true);
6071 if (type
== QType::NS
) {
6072 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6075 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString());
6084 vector
<DNSRecord
> ret
;
6085 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6086 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6087 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6088 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6089 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6090 /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
6091 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
6093 BOOST_CHECK_EQUAL(queriesCount
, 7);
6095 /* again, to test the cache */
6097 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6098 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6099 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6100 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6101 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6102 BOOST_CHECK_EQUAL(queriesCount
, 7);
6106 BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_ds
) {
6109 - parent is secure, zone is secure: DS should be secure
6111 std::unique_ptr
<SyncRes
> sr
;
6114 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6117 const DNSName
target("powerdns.com.");
6120 auto luaconfsCopy
= g_luaconfs
.getCopy();
6121 luaconfsCopy
.dsAnchors
.clear();
6122 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6123 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6124 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6126 g_luaconfs
.setState(luaconfsCopy
);
6128 size_t queriesCount
= 0;
6130 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
) {
6133 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6134 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6137 if (isRootServer(ip
)) {
6138 setLWResult(res
, 0, false, false, true);
6139 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6140 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6141 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6142 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6150 vector
<DNSRecord
> ret
;
6151 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6152 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6153 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6154 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6155 for (const auto& record
: ret
) {
6156 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6158 BOOST_CHECK_EQUAL(queriesCount
, 4);
6160 /* again, to test the cache */
6162 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6163 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6164 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6165 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6166 for (const auto& record
: ret
) {
6167 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6169 BOOST_CHECK_EQUAL(queriesCount
, 4);
6172 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_ds
) {
6175 - parent is secure, zone is insecure: DS denial should be secure
6177 std::unique_ptr
<SyncRes
> sr
;
6180 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6183 const DNSName
target("powerdns.com.");
6186 auto luaconfsCopy
= g_luaconfs
.getCopy();
6187 luaconfsCopy
.dsAnchors
.clear();
6188 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6189 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6191 g_luaconfs
.setState(luaconfsCopy
);
6193 size_t queriesCount
= 0;
6195 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
) {
6198 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6199 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6202 if (isRootServer(ip
)) {
6203 setLWResult(res
, 0, false, false, true);
6204 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6205 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6206 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6207 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6215 vector
<DNSRecord
> ret
;
6216 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6217 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6218 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6219 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6220 for (const auto& record
: ret
) {
6221 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6223 BOOST_CHECK_EQUAL(queriesCount
, 4);
6225 /* again, to test the cache */
6227 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6228 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6229 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6230 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6231 for (const auto& record
: ret
) {
6232 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6234 BOOST_CHECK_EQUAL(queriesCount
, 4);
6237 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut
) {
6238 std::unique_ptr
<SyncRes
> sr
;
6241 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6244 const DNSName
target("www.sub.powerdns.com.");
6245 const ComboAddress
targetAddr("192.0.2.42");
6248 auto luaconfsCopy
= g_luaconfs
.getCopy();
6249 luaconfsCopy
.dsAnchors
.clear();
6250 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6251 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6252 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6254 g_luaconfs
.setState(luaconfsCopy
);
6256 size_t queriesCount
= 0;
6258 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
) {
6261 if (type
== QType::DS
) {
6262 if (domain
== DNSName("sub.powerdns.com.")) {
6263 setLWResult(res
, 0, false, false, true);
6264 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6265 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6266 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6267 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6270 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6271 setLWResult(res
, 0, false, false, true);
6272 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);
6276 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6279 else if (type
== QType::DNSKEY
) {
6280 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6281 setLWResult(res
, 0, true, false, true);
6282 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6283 addRRSIG(keys
, res
->d_records
, domain
, 300);
6287 setLWResult(res
, 0, false, false, true);
6288 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6293 if (isRootServer(ip
)) {
6294 setLWResult(res
, 0, false, false, true);
6295 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6296 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6297 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6298 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6301 else if (ip
== ComboAddress("192.0.2.1:53")) {
6302 if (domain
== DNSName("com.")) {
6303 setLWResult(res
, 0, true, false, true);
6304 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6305 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6306 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6309 setLWResult(res
, 0, false, false, true);
6310 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6311 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6312 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6313 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6317 else if (ip
== ComboAddress("192.0.2.2:53")) {
6318 setLWResult(res
, 0, true, false, true);
6319 if (type
== QType::NS
) {
6320 if (domain
== DNSName("www.sub.powerdns.com.")) {
6321 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);
6323 else if (domain
== DNSName("sub.powerdns.com.")) {
6324 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6326 else if (domain
== DNSName("powerdns.com.")) {
6327 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6328 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6331 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6340 vector
<DNSRecord
> ret
;
6341 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6342 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6343 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6344 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6345 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6346 BOOST_CHECK_EQUAL(queriesCount
, 9);
6348 /* again, to test the cache */
6350 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6351 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6352 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6353 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6354 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6355 BOOST_CHECK_EQUAL(queriesCount
, 9);
6358 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut
) {
6359 std::unique_ptr
<SyncRes
> sr
;
6362 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6365 const DNSName
target("www.sub.powerdns.com.");
6366 const ComboAddress
targetAddr("192.0.2.42");
6369 auto luaconfsCopy
= g_luaconfs
.getCopy();
6370 luaconfsCopy
.dsAnchors
.clear();
6371 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6372 /* No key material for .com */
6373 /* But TA for sub.powerdns.com. */
6374 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6375 luaconfsCopy
.dsAnchors
[DNSName("sub.powerdns.com.")].insert(keys
[DNSName("sub.powerdns.com.")].second
);
6376 g_luaconfs
.setState(luaconfsCopy
);
6378 size_t queriesCount
= 0;
6380 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
) {
6383 if (type
== QType::DS
) {
6384 if (domain
== DNSName("www.sub.powerdns.com")) {
6385 setLWResult(res
, 0, false, false, true);
6386 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);
6387 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6388 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6389 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6392 setLWResult(res
, 0, false, false, true);
6394 if (domain
== DNSName("com.")) {
6395 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6397 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6398 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6401 setLWResult(res
, 0, false, false, true);
6402 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6407 else if (type
== QType::DNSKEY
) {
6408 if (domain
== g_rootdnsname
|| domain
== DNSName("sub.powerdns.com.")) {
6409 setLWResult(res
, 0, true, false, true);
6410 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6411 addRRSIG(keys
, res
->d_records
, domain
, 300);
6416 if (isRootServer(ip
)) {
6417 setLWResult(res
, 0, false, false, true);
6418 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6420 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { 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 (domain
== DNSName("com.")) {
6427 setLWResult(res
, 0, true, false, true);
6428 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6429 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6431 else if (domain
.isPartOf(DNSName("powerdns.com."))) {
6432 setLWResult(res
, 0, false, false, true);
6433 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6434 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6438 else if (ip
== ComboAddress("192.0.2.2:53")) {
6439 setLWResult(res
, 0, true, false, true);
6440 if (type
== QType::NS
) {
6441 if (domain
== DNSName("www.sub.powerdns.com.")) {
6442 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);
6443 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6444 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6445 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6447 else if (domain
== DNSName("sub.powerdns.com.")) {
6448 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6449 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6451 else if (domain
== DNSName("powerdns.com.")) {
6452 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6455 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6456 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6457 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6466 vector
<DNSRecord
> ret
;
6467 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6468 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6469 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6470 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6471 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6472 BOOST_CHECK_EQUAL(queriesCount
, 7);
6474 /* again, to test the cache */
6476 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6477 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6478 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6479 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6480 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6481 BOOST_CHECK_EQUAL(queriesCount
, 7);
6484 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata
) {
6485 std::unique_ptr
<SyncRes
> sr
;
6488 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6491 const DNSName
target("powerdns.com.");
6494 auto luaconfsCopy
= g_luaconfs
.getCopy();
6495 luaconfsCopy
.dsAnchors
.clear();
6496 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6497 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6499 g_luaconfs
.setState(luaconfsCopy
);
6501 size_t queriesCount
= 0;
6503 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
) {
6506 if (type
== QType::DS
) {
6507 if (domain
== target
) {
6508 setLWResult(res
, 0, false, false, true);
6509 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6510 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6511 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6515 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6518 else if (type
== QType::DNSKEY
) {
6519 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6520 setLWResult(res
, 0, true, false, true);
6521 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6522 addRRSIG(keys
, res
->d_records
, domain
, 300);
6526 setLWResult(res
, 0, false, false, true);
6527 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6532 if (isRootServer(ip
)) {
6533 setLWResult(res
, 0, false, false, true);
6534 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6535 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6536 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6537 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6540 else if (ip
== ComboAddress("192.0.2.1:53")) {
6541 if (domain
== DNSName("com.")) {
6542 setLWResult(res
, 0, true, false, true);
6543 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6544 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6545 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6546 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6549 setLWResult(res
, 0, false, false, true);
6550 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6552 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6553 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6554 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6558 else if (ip
== ComboAddress("192.0.2.2:53")) {
6559 if (type
== QType::NS
) {
6560 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6561 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6564 setLWResult(res
, 0, true, false, true);
6565 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6574 vector
<DNSRecord
> ret
;
6575 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6576 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6577 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6578 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6579 /* 4 NS (com from root, com from com, powerdns.com from com,
6580 powerdns.com from powerdns.com)
6581 2 DNSKEY (. and com., none for powerdns.com because no DS)
6584 BOOST_CHECK_EQUAL(queriesCount
, 7);
6586 /* again, to test the cache */
6588 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6589 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6590 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6591 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6592 BOOST_CHECK_EQUAL(queriesCount
, 7);
6595 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname
) {
6596 std::unique_ptr
<SyncRes
> sr
;
6599 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6602 const DNSName
target("powerdns.com.");
6603 const DNSName
targetCName("power-dns.com.");
6604 const ComboAddress
targetCNameAddr("192.0.2.42");
6607 auto luaconfsCopy
= g_luaconfs
.getCopy();
6608 luaconfsCopy
.dsAnchors
.clear();
6609 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6610 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6611 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6612 g_luaconfs
.setState(luaconfsCopy
);
6614 size_t queriesCount
= 0;
6616 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
) {
6619 if (type
== QType::DS
) {
6620 if (domain
== targetCName
) {
6621 setLWResult(res
, 0, false, false, true);
6622 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6623 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6624 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6628 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6631 else if (type
== QType::DNSKEY
) {
6632 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6633 setLWResult(res
, 0, true, false, true);
6634 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6635 addRRSIG(keys
, res
->d_records
, domain
, 300);
6639 setLWResult(res
, 0, false, false, true);
6640 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6645 if (isRootServer(ip
)) {
6646 setLWResult(res
, 0, false, false, true);
6647 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6648 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6649 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6650 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6653 else if (ip
== ComboAddress("192.0.2.1:53")) {
6654 setLWResult(res
, 0, false, false, true);
6655 if (domain
== DNSName("com.")) {
6656 setLWResult(res
, 0, true, false, true);
6657 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6658 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6659 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6660 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6663 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6664 if (domain
== DNSName("powerdns.com.")) {
6665 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6667 else if (domain
== targetCName
) {
6668 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6670 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6671 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6676 else if (ip
== ComboAddress("192.0.2.2:53")) {
6677 setLWResult(res
, 0, true, false, true);
6679 if (type
== QType::NS
) {
6680 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6681 if (domain
== DNSName("powerdns.com.")) {
6682 addRRSIG(keys
, res
->d_records
, domain
, 300);
6684 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6685 if (domain
== DNSName("powerdns.com.")) {
6686 addRRSIG(keys
, res
->d_records
, domain
, 300);
6690 if (domain
== DNSName("powerdns.com.")) {
6691 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6692 addRRSIG(keys
, res
->d_records
, domain
, 300);
6694 else if (domain
== targetCName
) {
6695 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6706 vector
<DNSRecord
> ret
;
6707 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6708 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6709 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6710 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6711 BOOST_CHECK_EQUAL(queriesCount
, 11);
6713 /* again, to test the cache */
6715 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6716 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6717 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6718 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6719 BOOST_CHECK_EQUAL(queriesCount
, 11);
6722 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname
) {
6723 std::unique_ptr
<SyncRes
> sr
;
6726 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6729 const DNSName
target("power-dns.com.");
6730 const DNSName
targetCName("powerdns.com.");
6731 const ComboAddress
targetCNameAddr("192.0.2.42");
6734 auto luaconfsCopy
= g_luaconfs
.getCopy();
6735 luaconfsCopy
.dsAnchors
.clear();
6736 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6737 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6738 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6739 g_luaconfs
.setState(luaconfsCopy
);
6741 size_t queriesCount
= 0;
6743 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
) {
6746 if (type
== QType::DS
) {
6747 if (domain
== DNSName("power-dns.com.")) {
6748 setLWResult(res
, 0, false, false, true);
6749 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6750 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6751 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6755 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6758 else if (type
== QType::DNSKEY
) {
6759 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6760 setLWResult(res
, 0, true, false, true);
6761 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6762 addRRSIG(keys
, res
->d_records
, domain
, 300);
6766 setLWResult(res
, 0, false, false, true);
6767 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6772 if (isRootServer(ip
)) {
6773 setLWResult(res
, 0, false, false, true);
6774 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6775 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6776 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6777 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6780 else if (ip
== ComboAddress("192.0.2.1:53")) {
6781 if (domain
== DNSName("com.")) {
6782 setLWResult(res
, 0, true, false, true);
6783 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6784 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6785 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6786 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6788 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
6789 setLWResult(res
, 0, false, false, true);
6790 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6791 if (domain
== targetCName
) {
6792 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6794 else if (domain
== target
) {
6795 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6797 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6798 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6802 else if (ip
== ComboAddress("192.0.2.2:53")) {
6803 setLWResult(res
, 0, true, false, true);
6804 if (type
== QType::NS
) {
6805 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6806 if (domain
== DNSName("powerdns.com.")) {
6807 addRRSIG(keys
, res
->d_records
, domain
, 300);
6809 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6810 if (domain
== DNSName("powerdns.com.")) {
6811 addRRSIG(keys
, res
->d_records
, domain
, 300);
6815 if (domain
== target
) {
6816 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6818 else if (domain
== targetCName
) {
6819 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6820 addRRSIG(keys
, res
->d_records
, domain
, 300);
6830 vector
<DNSRecord
> ret
;
6831 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6832 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6833 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6834 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6835 BOOST_CHECK_EQUAL(queriesCount
, 11);
6837 /* again, to test the cache */
6839 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6840 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6841 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6842 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6843 BOOST_CHECK_EQUAL(queriesCount
, 11);
6846 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname
) {
6847 std::unique_ptr
<SyncRes
> sr
;
6850 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6853 const DNSName
target("power-dns.com.");
6854 const DNSName
targetCName("powerdns.com.");
6855 const ComboAddress
targetCNameAddr("192.0.2.42");
6858 auto luaconfsCopy
= g_luaconfs
.getCopy();
6859 luaconfsCopy
.dsAnchors
.clear();
6860 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6861 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6862 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6863 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6864 g_luaconfs
.setState(luaconfsCopy
);
6866 size_t queriesCount
= 0;
6868 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
) {
6871 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6872 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6875 if (isRootServer(ip
)) {
6876 setLWResult(res
, 0, false, false, true);
6877 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6878 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6879 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6880 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6883 else if (ip
== ComboAddress("192.0.2.1:53")) {
6884 if (domain
== DNSName("com.")) {
6885 setLWResult(res
, 0, true, false, true);
6886 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6887 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6888 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6889 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6891 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
6892 setLWResult(res
, 0, false, false, true);
6893 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6894 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
6895 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6896 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6900 else if (ip
== ComboAddress("192.0.2.2:53")) {
6901 setLWResult(res
, 0, true, false, true);
6902 if (type
== QType::NS
) {
6903 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6904 addRRSIG(keys
, res
->d_records
, domain
, 300);
6905 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6906 addRRSIG(keys
, res
->d_records
, domain
, 300);
6909 if (domain
== target
) {
6910 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6911 /* No RRSIG, leading to bogus */
6913 else if (domain
== targetCName
) {
6914 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6915 addRRSIG(keys
, res
->d_records
, domain
, 300);
6925 vector
<DNSRecord
> ret
;
6926 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6927 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6928 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6929 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6930 BOOST_CHECK_EQUAL(queriesCount
, 11);
6932 /* again, to test the cache */
6934 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6935 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6936 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6937 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6938 BOOST_CHECK_EQUAL(queriesCount
, 11);
6941 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname
) {
6942 std::unique_ptr
<SyncRes
> sr
;
6945 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6948 const DNSName
target("power-dns.com.");
6949 const DNSName
targetCName("powerdns.com.");
6950 const ComboAddress
targetCNameAddr("192.0.2.42");
6953 auto luaconfsCopy
= g_luaconfs
.getCopy();
6954 luaconfsCopy
.dsAnchors
.clear();
6955 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6956 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6957 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6958 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6959 g_luaconfs
.setState(luaconfsCopy
);
6961 size_t queriesCount
= 0;
6963 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
) {
6966 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6967 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6970 if (isRootServer(ip
)) {
6971 setLWResult(res
, 0, false, false, true);
6972 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6973 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6974 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6975 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6978 else if (ip
== ComboAddress("192.0.2.1:53")) {
6979 if (domain
== DNSName("com.")) {
6980 setLWResult(res
, 0, true, false, true);
6981 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6982 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6983 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6984 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6986 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
6987 setLWResult(res
, 0, false, false, true);
6988 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6989 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
6990 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6991 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6995 else if (ip
== ComboAddress("192.0.2.2:53")) {
6996 setLWResult(res
, 0, true, false, true);
6997 if (type
== QType::NS
) {
6998 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6999 addRRSIG(keys
, res
->d_records
, domain
, 300);
7000 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7001 addRRSIG(keys
, res
->d_records
, domain
, 300);
7004 if (domain
== target
) {
7005 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7006 addRRSIG(keys
, res
->d_records
, domain
, 300);
7008 else if (domain
== targetCName
) {
7009 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7010 /* No RRSIG, leading to bogus */
7020 vector
<DNSRecord
> ret
;
7021 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7022 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7023 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7024 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7025 BOOST_CHECK_EQUAL(queriesCount
, 11);
7027 /* again, to test the cache */
7029 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7030 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7031 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7032 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7033 BOOST_CHECK_EQUAL(queriesCount
, 11);
7036 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname
) {
7037 std::unique_ptr
<SyncRes
> sr
;
7040 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7043 const DNSName
target("power-dns.com.");
7044 const DNSName
targetCName("powerdns.com.");
7045 const ComboAddress
targetCNameAddr("192.0.2.42");
7048 auto luaconfsCopy
= g_luaconfs
.getCopy();
7049 luaconfsCopy
.dsAnchors
.clear();
7050 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7051 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7052 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7053 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7054 g_luaconfs
.setState(luaconfsCopy
);
7056 size_t queriesCount
= 0;
7058 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
) {
7061 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7062 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7065 if (isRootServer(ip
)) {
7066 setLWResult(res
, 0, false, false, true);
7067 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7068 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7069 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7070 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7073 else if (ip
== ComboAddress("192.0.2.1:53")) {
7074 if (domain
== DNSName("com.")) {
7075 setLWResult(res
, 0, true, false, true);
7076 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7077 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7078 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7079 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7081 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7082 setLWResult(res
, 0, false, false, true);
7083 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7084 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7085 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7086 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7090 else if (ip
== ComboAddress("192.0.2.2:53")) {
7091 setLWResult(res
, 0, true, false, true);
7092 if (type
== QType::NS
) {
7093 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7094 addRRSIG(keys
, res
->d_records
, domain
, 300);
7095 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7096 addRRSIG(keys
, res
->d_records
, domain
, 300);
7099 if (domain
== target
) {
7100 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7101 addRRSIG(keys
, res
->d_records
, domain
, 300);
7103 else if (domain
== targetCName
) {
7104 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7105 addRRSIG(keys
, res
->d_records
, domain
, 300);
7115 vector
<DNSRecord
> ret
;
7116 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7117 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7118 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7119 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7120 BOOST_CHECK_EQUAL(queriesCount
, 12);
7122 /* again, to test the cache */
7124 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7125 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7126 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7127 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7128 BOOST_CHECK_EQUAL(queriesCount
, 12);
7131 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname
) {
7132 std::unique_ptr
<SyncRes
> sr
;
7135 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7138 const DNSName
target("powerdns.com.");
7139 const DNSName
targetCName("power-dns.com.");
7140 const ComboAddress
targetCNameAddr("192.0.2.42");
7143 auto luaconfsCopy
= g_luaconfs
.getCopy();
7144 luaconfsCopy
.dsAnchors
.clear();
7145 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7146 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7147 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7148 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7149 g_luaconfs
.setState(luaconfsCopy
);
7151 size_t queriesCount
= 0;
7153 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
) {
7156 if (type
== QType::DS
) {
7157 if (domain
== DNSName("power-dns.com.")) {
7158 setLWResult(res
, 0, false, false, true);
7159 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7160 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7161 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7165 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7168 else if (type
== QType::DNSKEY
) {
7169 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7170 setLWResult(res
, 0, true, false, true);
7171 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7172 addRRSIG(keys
, res
->d_records
, domain
, 300);
7176 setLWResult(res
, 0, false, false, true);
7177 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7182 if (isRootServer(ip
)) {
7183 setLWResult(res
, 0, false, false, true);
7184 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7185 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7186 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7187 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7190 else if (ip
== ComboAddress("192.0.2.1:53")) {
7191 if (domain
== DNSName("com.")) {
7192 setLWResult(res
, 0, true, false, true);
7193 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7194 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7195 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7196 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7198 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7199 setLWResult(res
, 0, false, false, true);
7200 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7201 if (domain
== DNSName("powerdns.com.")) {
7202 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7204 else if (domain
== targetCName
) {
7205 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7207 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7208 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7212 else if (ip
== ComboAddress("192.0.2.2:53")) {
7213 setLWResult(res
, 0, true, false, true);
7214 if (type
== QType::NS
) {
7215 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7216 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7219 if (domain
== DNSName("powerdns.com.")) {
7220 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7221 /* No RRSIG -> Bogus */
7223 else if (domain
== targetCName
) {
7224 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7234 vector
<DNSRecord
> ret
;
7235 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7236 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7237 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7238 /* no RRSIG to show */
7239 BOOST_CHECK_EQUAL(ret
.size(), 2);
7240 BOOST_CHECK_EQUAL(queriesCount
, 10);
7242 /* again, to test the cache */
7244 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7245 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7246 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7247 BOOST_CHECK_EQUAL(ret
.size(), 2);
7248 BOOST_CHECK_EQUAL(queriesCount
, 10);
7251 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta
) {
7252 std::unique_ptr
<SyncRes
> sr
;
7255 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7258 const DNSName
target("powerdns.com.");
7259 const ComboAddress
targetAddr("192.0.2.42");
7262 auto luaconfsCopy
= g_luaconfs
.getCopy();
7263 luaconfsCopy
.dsAnchors
.clear();
7264 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7265 /* No key material for .com */
7266 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7267 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7268 g_luaconfs
.setState(luaconfsCopy
);
7270 size_t queriesCount
= 0;
7272 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
) {
7275 if (type
== QType::DNSKEY
) {
7276 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7277 setLWResult(res
, 0, true, false, true);
7278 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7279 addRRSIG(keys
, res
->d_records
, domain
, 300);
7282 else if (domain
== DNSName("com.")) {
7283 setLWResult(res
, 0, false, false, true);
7284 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7289 if (isRootServer(ip
)) {
7290 setLWResult(res
, 0, false, false, true);
7291 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7292 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7293 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7294 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7297 else if (ip
== ComboAddress("192.0.2.1:53")) {
7298 if (target
== domain
) {
7299 setLWResult(res
, 0, false, false, true);
7300 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7301 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7303 else if (domain
== DNSName("com.")) {
7304 setLWResult(res
, 0, true, false, true);
7305 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7306 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7310 else if (ip
== ComboAddress("192.0.2.2:53")) {
7311 setLWResult(res
, 0, true, false, true);
7312 if (type
== QType::NS
) {
7313 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7316 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7318 addRRSIG(keys
, res
->d_records
, domain
, 300);
7326 vector
<DNSRecord
> ret
;
7327 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7328 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7329 /* should be insecure but we have a TA for powerdns.com. */
7330 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7331 /* We got a RRSIG */
7332 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7333 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7334 BOOST_CHECK_EQUAL(queriesCount
, 5);
7336 /* again, to test the cache */
7338 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7339 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7340 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7341 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7342 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7343 BOOST_CHECK_EQUAL(queriesCount
, 5);
7346 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig
) {
7347 std::unique_ptr
<SyncRes
> sr
;
7350 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7353 const DNSName
target("powerdns.com.");
7354 const ComboAddress
targetAddr("192.0.2.42");
7357 auto luaconfsCopy
= g_luaconfs
.getCopy();
7358 luaconfsCopy
.dsAnchors
.clear();
7359 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7360 /* No key material for .com */
7361 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7362 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7363 g_luaconfs
.setState(luaconfsCopy
);
7365 size_t queriesCount
= 0;
7367 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
) {
7370 if (type
== QType::DNSKEY
) {
7371 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7372 setLWResult(res
, 0, true, false, true);
7373 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7374 addRRSIG(keys
, res
->d_records
, domain
, 300);
7377 else if (domain
== DNSName("com.")) {
7378 setLWResult(res
, 0, false, false, true);
7379 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7384 if (target
.isPartOf(domain
) && isRootServer(ip
)) {
7385 setLWResult(res
, 0, false, false, true);
7386 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7387 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7388 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7389 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7392 else if (ip
== ComboAddress("192.0.2.1:53")) {
7393 if (target
== domain
) {
7394 setLWResult(res
, 0, false, false, true);
7395 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7396 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7398 else if (domain
== DNSName("com.")) {
7399 setLWResult(res
, 0, true, false, true);
7400 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7401 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7405 else if (domain
== target
&& ip
== ComboAddress("192.0.2.2:53")) {
7406 setLWResult(res
, 0, true, false, true);
7407 if (type
== QType::NS
) {
7408 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7411 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7413 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
7421 vector
<DNSRecord
> ret
;
7422 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7423 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7424 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
7425 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7427 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7428 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7429 BOOST_CHECK_EQUAL(queriesCount
, 4);
7431 /* again, to test the cache */
7433 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7434 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7435 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7436 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7437 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7438 BOOST_CHECK_EQUAL(queriesCount
, 4);
7441 BOOST_AUTO_TEST_CASE(test_dnssec_nta
) {
7442 std::unique_ptr
<SyncRes
> sr
;
7445 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7448 const DNSName
target(".");
7451 auto luaconfsCopy
= g_luaconfs
.getCopy();
7452 luaconfsCopy
.dsAnchors
.clear();
7453 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7454 /* Add a NTA for "." */
7455 luaconfsCopy
.negAnchors
[g_rootdnsname
] = "NTA for Root";
7456 g_luaconfs
.setState(luaconfsCopy
);
7458 size_t queriesCount
= 0;
7460 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
) {
7463 if (domain
== target
&& type
== QType::NS
) {
7465 setLWResult(res
, 0, true, false, true);
7466 char addr
[] = "a.root-servers.net.";
7467 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
7469 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
7472 addRRSIG(keys
, res
->d_records
, domain
, 300);
7474 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
7475 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
7478 } else if (domain
== target
&& type
== QType::DNSKEY
) {
7480 setLWResult(res
, 0, true, false, true);
7490 vector
<DNSRecord
> ret
;
7491 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7492 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7493 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7494 /* 13 NS + 1 RRSIG */
7495 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
7496 BOOST_CHECK_EQUAL(queriesCount
, 1);
7498 /* again, to test the cache */
7500 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7501 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7502 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7503 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
7504 BOOST_CHECK_EQUAL(queriesCount
, 1);
7507 BOOST_AUTO_TEST_CASE(test_dnssec_no_ta
) {
7508 std::unique_ptr
<SyncRes
> sr
;
7511 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7514 const DNSName
target(".");
7517 /* Remove the root DS */
7518 auto luaconfsCopy
= g_luaconfs
.getCopy();
7519 luaconfsCopy
.dsAnchors
.clear();
7520 g_luaconfs
.setState(luaconfsCopy
);
7522 size_t queriesCount
= 0;
7524 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
) {
7527 if (domain
== target
&& type
== QType::NS
) {
7529 setLWResult(res
, 0, true, false, true);
7530 char addr
[] = "a.root-servers.net.";
7531 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
7533 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
7536 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
7537 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
7545 vector
<DNSRecord
> ret
;
7546 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7547 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7548 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7549 /* 13 NS + 0 RRSIG */
7550 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
7551 BOOST_CHECK_EQUAL(queriesCount
, 1);
7553 /* again, to test the cache */
7555 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7556 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7557 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7558 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
7559 BOOST_CHECK_EQUAL(queriesCount
, 1);
7562 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata
) {
7563 std::unique_ptr
<SyncRes
> sr
;
7566 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7569 const DNSName
target("powerdns.com.");
7572 auto luaconfsCopy
= g_luaconfs
.getCopy();
7573 luaconfsCopy
.dsAnchors
.clear();
7574 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7575 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7576 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7577 g_luaconfs
.setState(luaconfsCopy
);
7579 size_t queriesCount
= 0;
7581 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
) {
7584 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7585 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7589 setLWResult(res
, 0, true, false, true);
7596 vector
<DNSRecord
> ret
;
7597 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7598 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7599 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7600 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
7601 /* com|NS, powerdns.com|NS, powerdns.com|A */
7602 BOOST_CHECK_EQUAL(queriesCount
, 3);
7604 /* again, to test the cache */
7606 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7607 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7608 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7609 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
7610 /* we don't store empty results */
7611 BOOST_CHECK_EQUAL(queriesCount
, 4);
7614 BOOST_AUTO_TEST_CASE(test_nsec_denial_nowrap
) {
7618 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7620 vector
<DNSRecord
> records
;
7622 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7623 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7627 a.example.org. -> d.example.org. denies the existence of b.example.org.
7629 addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7630 recordContents
.push_back(records
.at(0).d_content
);
7631 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7632 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7635 ContentSigPair pair
;
7636 pair
.records
= recordContents
;
7637 pair
.signatures
= signatureContents
;
7639 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
7641 /* add wildcard denial */
7642 recordContents
.clear();
7643 signatureContents
.clear();
7644 addNSECRecordToLW(DNSName("example.org."), DNSName("+.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7645 recordContents
.push_back(records
.at(0).d_content
);
7646 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7647 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7650 pair
.records
= recordContents
;
7651 pair
.signatures
= signatureContents
;
7652 denialMap
[std::make_pair(DNSName("example.org."), QType::NSEC
)] = pair
;
7654 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
7655 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7657 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7658 /* let's check that d.example.org. is not denied by this proof */
7659 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7662 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_1
) {
7666 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7668 vector
<DNSRecord
> records
;
7670 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7671 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7674 Wrap case 1 test case:
7675 z.example.org. -> b.example.org. denies the existence of a.example.org.
7677 addNSECRecordToLW(DNSName("z.example.org."), DNSName("b.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7678 recordContents
.push_back(records
.at(0).d_content
);
7679 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7680 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7683 ContentSigPair pair
;
7684 pair
.records
= recordContents
;
7685 pair
.signatures
= signatureContents
;
7687 denialMap
[std::make_pair(DNSName("z.example.org."), QType::NSEC
)] = pair
;
7689 dState denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
7690 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7692 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7693 /* let's check that d.example.org. is not denied by this proof */
7694 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7697 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_2
) {
7701 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7703 vector
<DNSRecord
> records
;
7705 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7706 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7709 Wrap case 2 test case:
7710 y.example.org. -> a.example.org. denies the existence of z.example.org.
7712 addNSECRecordToLW(DNSName("y.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7713 recordContents
.push_back(records
.at(0).d_content
);
7714 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7715 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7718 ContentSigPair pair
;
7719 pair
.records
= recordContents
;
7720 pair
.signatures
= signatureContents
;
7722 denialMap
[std::make_pair(DNSName("y.example.org."), QType::NSEC
)] = pair
;
7724 dState denialState
= getDenial(denialMap
, DNSName("z.example.org."), QType::A
, false, false);
7725 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7727 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7728 /* let's check that d.example.org. is not denied by this proof */
7729 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7732 BOOST_AUTO_TEST_CASE(test_nsec_denial_only_one_nsec
) {
7736 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7738 vector
<DNSRecord
> records
;
7740 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7741 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7744 Only one NSEC in the whole zone test case:
7745 a.example.org. -> a.example.org. denies the existence of b.example.org.
7747 addNSECRecordToLW(DNSName("a.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7748 recordContents
.push_back(records
.at(0).d_content
);
7749 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7750 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7753 ContentSigPair pair
;
7754 pair
.records
= recordContents
;
7755 pair
.signatures
= signatureContents
;
7757 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
7759 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
7760 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7762 denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
7763 /* let's check that d.example.org. is not denied by this proof */
7764 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7767 BOOST_AUTO_TEST_CASE(test_nsec_root_nxd_denial
) {
7771 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7773 vector
<DNSRecord
> records
;
7775 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7776 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7779 The RRSIG from "." denies the existence of anything between a. and c.,
7782 addNSECRecordToLW(DNSName("a."), DNSName("c."), { QType::NS
}, 600, records
);
7783 recordContents
.push_back(records
.at(0).d_content
);
7784 addRRSIG(keys
, records
, DNSName("."), 300);
7785 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7788 ContentSigPair pair
;
7789 pair
.records
= recordContents
;
7790 pair
.signatures
= signatureContents
;
7792 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
7794 /* add wildcard denial */
7795 recordContents
.clear();
7796 signatureContents
.clear();
7797 addNSECRecordToLW(DNSName("."), DNSName("+"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7798 recordContents
.push_back(records
.at(0).d_content
);
7799 addRRSIG(keys
, records
, DNSName("."), 300);
7800 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7803 pair
.records
= recordContents
;
7804 pair
.signatures
= signatureContents
;
7805 denialMap
[std::make_pair(DNSName("."), QType::NSEC
)] = pair
;
7807 dState denialState
= getDenial(denialMap
, DNSName("b."), QType::A
, false, false);
7808 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7811 BOOST_AUTO_TEST_CASE(test_nsec_ancestor_nxqtype_denial
) {
7815 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7817 vector
<DNSRecord
> records
;
7819 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7820 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7823 The RRSIG from "." denies the existence of any type except NS at a.
7824 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
7825 signer field that is shorter than the owner name of the NSEC RR) it can't
7826 be used to deny anything except the whole name or a DS.
7828 addNSECRecordToLW(DNSName("a."), DNSName("b."), { QType::NS
}, 600, records
);
7829 recordContents
.push_back(records
.at(0).d_content
);
7830 addRRSIG(keys
, records
, DNSName("."), 300);
7831 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7834 ContentSigPair pair
;
7835 pair
.records
= recordContents
;
7836 pair
.signatures
= signatureContents
;
7838 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
7840 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
7841 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
7842 nonexistence of any RRs below that zone cut, which include all RRs at
7843 that (original) owner name other than DS RRs, and all RRs below that
7844 owner name regardless of type.
7847 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, false);
7848 /* no data means the qname/qtype is not denied, because an ancestor
7849 delegation NSEC can only deny the DS */
7850 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7852 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
7853 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
7856 BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial
) {
7860 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7862 vector
<DNSRecord
> records
;
7864 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7865 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7868 * RFC 5155 section 8.9:
7869 * If there is an NSEC3 RR present in the response that matches the
7870 * delegation name, then the validator MUST ensure that the NS bit is
7871 * set and that the DS bit is not set in the Type Bit Maps field of the
7875 The RRSIG from "." denies the existence of any type at a.
7876 NS should be set if it was proving an insecure delegation, let's check that
7877 we correctly detect that it's not.
7879 addNSECRecordToLW(DNSName("a."), DNSName("b."), { }, 600, records
);
7880 recordContents
.push_back(records
.at(0).d_content
);
7881 addRRSIG(keys
, records
, DNSName("."), 300);
7882 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7885 ContentSigPair pair
;
7886 pair
.records
= recordContents
;
7887 pair
.signatures
= signatureContents
;
7889 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
7891 /* Insecure because the NS is not set, so while it does
7892 denies the DS, it can't prove an insecure delegation */
7893 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
7894 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7897 BOOST_AUTO_TEST_CASE(test_nsec_nxqtype_cname
) {
7901 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7903 vector
<DNSRecord
> records
;
7905 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7906 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7908 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::CNAME
}, 600, records
);
7909 recordContents
.push_back(records
.at(0).d_content
);
7910 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
7911 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7914 ContentSigPair pair
;
7915 pair
.records
= recordContents
;
7916 pair
.signatures
= signatureContents
;
7918 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
7920 /* this NSEC is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
7921 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, true, true);
7922 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7925 BOOST_AUTO_TEST_CASE(test_nsec3_nxqtype_cname
) {
7929 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7931 vector
<DNSRecord
> records
;
7933 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7934 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7936 addNSEC3UnhashedRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::CNAME
}, 600, records
);
7937 recordContents
.push_back(records
.at(0).d_content
);
7938 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
7939 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7941 ContentSigPair pair
;
7942 pair
.records
= recordContents
;
7943 pair
.signatures
= signatureContents
;
7945 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
7948 /* this NSEC3 is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
7949 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, false, true);
7950 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7953 BOOST_AUTO_TEST_CASE(test_nsec_nxdomain_denial_missing_wildcard
) {
7957 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7959 vector
<DNSRecord
> records
;
7961 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7962 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7964 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("d.powerdns.com"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7965 recordContents
.push_back(records
.at(0).d_content
);
7966 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
7967 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7970 ContentSigPair pair
;
7971 pair
.records
= recordContents
;
7972 pair
.signatures
= signatureContents
;
7974 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
7976 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
7977 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7980 BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard
) {
7984 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7986 vector
<DNSRecord
> records
;
7988 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7989 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7991 addNSEC3NarrowRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7992 recordContents
.push_back(records
.at(0).d_content
);
7993 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
7994 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7996 ContentSigPair pair
;
7997 pair
.records
= recordContents
;
7998 pair
.signatures
= signatureContents
;
8000 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8002 /* Add NSEC3 for the closest encloser */
8003 recordContents
.clear();
8004 signatureContents
.clear();
8006 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8007 recordContents
.push_back(records
.at(0).d_content
);
8008 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8009 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8011 pair
.records
= recordContents
;
8012 pair
.signatures
= signatureContents
;
8013 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8015 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8016 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8019 BOOST_AUTO_TEST_CASE(test_nsec_ent_denial
) {
8023 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8025 vector
<DNSRecord
> records
;
8027 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8028 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8030 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::A
}, 600, records
);
8031 recordContents
.push_back(records
.at(0).d_content
);
8032 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8033 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8036 ContentSigPair pair
;
8037 pair
.records
= recordContents
;
8038 pair
.signatures
= signatureContents
;
8040 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8042 /* this NSEC is valid to prove a NXQTYPE at c.powerdns.com because it proves that
8044 dState denialState
= getDenial(denialMap
, DNSName("c.powerdns.com."), QType::AAAA
, true, true);
8045 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8047 /* this NSEC is not valid to prove a NXQTYPE at b.powerdns.com,
8048 it could prove a NXDOMAIN if it had an additional wildcard denial */
8049 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::AAAA
, true, true);
8050 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8052 /* this NSEC is not valid to prove a NXQTYPE for QType::A at a.c.powerdns.com either */
8053 denialState
= getDenial(denialMap
, DNSName("a.c.powerdns.com."), QType::A
, true, true);
8054 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8056 /* if we add the wildcard denial proof, we should get a NXDOMAIN proof for b.powerdns.com */
8057 recordContents
.clear();
8058 signatureContents
.clear();
8059 addNSECRecordToLW(DNSName(").powerdns.com."), DNSName("+.powerdns.com."), { }, 600, records
);
8060 recordContents
.push_back(records
.at(0).d_content
);
8061 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8062 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8064 pair
.records
= recordContents
;
8065 pair
.signatures
= signatureContents
;
8066 denialMap
[std::make_pair(DNSName(").powerdns.com."), QType::NSEC
)] = pair
;
8068 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, true, false);
8069 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8072 BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial
) {
8076 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8078 vector
<DNSRecord
> records
;
8080 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8081 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8084 The RRSIG from "." denies the existence of any type except NS at a.
8085 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8086 signer field that is shorter than the owner name of the NSEC RR) it can't
8087 be used to deny anything except the whole name or a DS.
8089 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::NS
}, 600, records
);
8090 recordContents
.push_back(records
.at(0).d_content
);
8091 addRRSIG(keys
, records
, DNSName("."), 300);
8092 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8094 ContentSigPair pair
;
8095 pair
.records
= recordContents
;
8096 pair
.signatures
= signatureContents
;
8098 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8101 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8102 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8103 nonexistence of any RRs below that zone cut, which include all RRs at
8104 that (original) owner name other than DS RRs, and all RRs below that
8105 owner name regardless of type.
8108 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8109 /* no data means the qname/qtype is not denied, because an ancestor
8110 delegation NSEC3 can only deny the DS */
8111 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8113 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8114 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8117 BOOST_AUTO_TEST_CASE(test_nsec3_denial_too_many_iterations
) {
8121 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8123 vector
<DNSRecord
> records
;
8125 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8126 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8128 /* adding a NSEC3 with more iterations that we support */
8129 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::AAAA
}, 600, records
, g_maxNSEC3Iterations
+ 100);
8130 recordContents
.push_back(records
.at(0).d_content
);
8131 addRRSIG(keys
, records
, DNSName("."), 300);
8132 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8134 ContentSigPair pair
;
8135 pair
.records
= recordContents
;
8136 pair
.signatures
= signatureContents
;
8138 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8141 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8142 /* since we refuse to compute more than g_maxNSEC3Iterations iterations, it should be Insecure */
8143 BOOST_CHECK_EQUAL(denialState
, INSECURE
);
8146 BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial
) {
8150 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8152 vector
<DNSRecord
> records
;
8154 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8155 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8158 * RFC 5155 section 8.9:
8159 * If there is an NSEC3 RR present in the response that matches the
8160 * delegation name, then the validator MUST ensure that the NS bit is
8161 * set and that the DS bit is not set in the Type Bit Maps field of the
8165 The RRSIG from "." denies the existence of any type at a.
8166 NS should be set if it was proving an insecure delegation, let's check that
8167 we correctly detect that it's not.
8169 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { }, 600, records
);
8170 recordContents
.push_back(records
.at(0).d_content
);
8171 addRRSIG(keys
, records
, DNSName("."), 300);
8172 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8174 ContentSigPair pair
;
8175 pair
.records
= recordContents
;
8176 pair
.signatures
= signatureContents
;
8178 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8181 /* Insecure because the NS is not set, so while it does
8182 denies the DS, it can't prove an insecure delegation */
8183 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8184 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8187 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_negcache_validity
) {
8188 std::unique_ptr
<SyncRes
> sr
;
8191 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8194 const DNSName
target("com.");
8197 auto luaconfsCopy
= g_luaconfs
.getCopy();
8198 luaconfsCopy
.dsAnchors
.clear();
8199 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8200 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8201 g_luaconfs
.setState(luaconfsCopy
);
8203 size_t queriesCount
= 0;
8205 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
) {
8208 DNSName auth
= domain
;
8211 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8212 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8215 setLWResult(res
, RCode::NoError
, true, false, true);
8216 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8217 addRRSIG(keys
, res
->d_records
, domain
, 300);
8218 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
8219 addRRSIG(keys
, res
->d_records
, domain
, 1);
8226 const time_t now
= time(nullptr);
8227 vector
<DNSRecord
> ret
;
8228 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8229 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8230 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8231 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8232 BOOST_CHECK_EQUAL(queriesCount
, 4);
8234 /* check that the entry has not been negatively cached for longer than the RRSIG validity */
8235 NegCache::NegCacheEntry ne
;
8236 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
8237 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
8238 BOOST_CHECK_EQUAL(ne
.d_ttd
, now
+ 1);
8239 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
8240 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
8241 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
8242 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
8244 /* again, to test the cache */
8246 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8247 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8248 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8249 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8250 BOOST_CHECK_EQUAL(queriesCount
, 4);
8253 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_cache_validity
) {
8254 std::unique_ptr
<SyncRes
> sr
;
8257 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8260 const DNSName
target("com.");
8261 const ComboAddress
targetAddr("192.0.2.42");
8264 auto luaconfsCopy
= g_luaconfs
.getCopy();
8265 luaconfsCopy
.dsAnchors
.clear();
8266 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8267 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8268 g_luaconfs
.setState(luaconfsCopy
);
8270 size_t queriesCount
= 0;
8272 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
) {
8275 DNSName auth
= domain
;
8278 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8279 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8282 setLWResult(res
, RCode::NoError
, true, false, true);
8283 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
8284 addRRSIG(keys
, res
->d_records
, domain
, 1);
8291 const time_t now
= time(nullptr);
8292 vector
<DNSRecord
> ret
;
8293 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8294 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8295 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8296 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8297 BOOST_CHECK_EQUAL(queriesCount
, 4);
8299 /* check that the entry has not been cached for longer than the RRSIG validity */
8300 const ComboAddress who
;
8301 vector
<DNSRecord
> cached
;
8302 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
8303 BOOST_REQUIRE_EQUAL(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
, &signatures
), 1);
8304 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
8305 BOOST_REQUIRE_EQUAL(signatures
.size(), 1);
8306 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), 1);
8308 /* again, to test the cache */
8310 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8311 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8312 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8313 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8314 BOOST_CHECK_EQUAL(queriesCount
, 4);
8317 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_secure
) {
8319 Validation is optional, and the first query does not ask for it,
8320 so the answer is cached as Indeterminate.
8321 The second query asks for validation, answer should be marked as
8324 std::unique_ptr
<SyncRes
> sr
;
8327 setDNSSECValidation(sr
, DNSSECMode::Process
);
8330 const DNSName
target("com.");
8333 auto luaconfsCopy
= g_luaconfs
.getCopy();
8334 luaconfsCopy
.dsAnchors
.clear();
8335 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8336 g_luaconfs
.setState(luaconfsCopy
);
8338 size_t queriesCount
= 0;
8340 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
) {
8343 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8344 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8347 if (domain
== target
&& type
== QType::A
) {
8348 setLWResult(res
, 0, true, false, true);
8349 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8350 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8358 vector
<DNSRecord
> ret
;
8359 /* first query does not require validation */
8360 sr
->setDNSSECValidationRequested(false);
8361 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8362 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8363 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8364 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8365 for (const auto& record
: ret
) {
8366 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8368 BOOST_CHECK_EQUAL(queriesCount
, 1);
8372 /* second one _does_ require validation */
8373 sr
->setDNSSECValidationRequested(true);
8374 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8375 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8376 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8377 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8378 for (const auto& record
: ret
) {
8379 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8381 BOOST_CHECK_EQUAL(queriesCount
, 3);
8384 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_insecure
) {
8386 Validation is optional, and the first query does not ask for it,
8387 so the answer is cached as Indeterminate.
8388 The second query asks for validation, answer should be marked as
8391 std::unique_ptr
<SyncRes
> sr
;
8394 setDNSSECValidation(sr
, DNSSECMode::Process
);
8397 const DNSName
target("com.");
8400 auto luaconfsCopy
= g_luaconfs
.getCopy();
8401 luaconfsCopy
.dsAnchors
.clear();
8402 g_luaconfs
.setState(luaconfsCopy
);
8404 size_t queriesCount
= 0;
8406 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
) {
8409 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8410 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8413 if (domain
== target
&& type
== QType::A
) {
8414 setLWResult(res
, 0, true, false, true);
8415 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8423 vector
<DNSRecord
> ret
;
8424 /* first query does not require validation */
8425 sr
->setDNSSECValidationRequested(false);
8426 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8427 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8428 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8429 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8430 for (const auto& record
: ret
) {
8431 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8433 BOOST_CHECK_EQUAL(queriesCount
, 1);
8437 /* second one _does_ require validation */
8438 sr
->setDNSSECValidationRequested(true);
8439 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8440 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8441 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8442 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8443 for (const auto& record
: ret
) {
8444 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8446 BOOST_CHECK_EQUAL(queriesCount
, 1);
8449 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_bogus
) {
8451 Validation is optional, and the first query does not ask for it,
8452 so the answer is cached as Indeterminate.
8453 The second query asks for validation, answer should be marked as
8456 std::unique_ptr
<SyncRes
> sr
;
8459 setDNSSECValidation(sr
, DNSSECMode::Process
);
8462 const DNSName
target("com.");
8465 auto luaconfsCopy
= g_luaconfs
.getCopy();
8466 luaconfsCopy
.dsAnchors
.clear();
8467 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8468 g_luaconfs
.setState(luaconfsCopy
);
8470 size_t queriesCount
= 0;
8472 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
) {
8475 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8476 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8479 if (domain
== target
&& type
== QType::A
) {
8480 setLWResult(res
, 0, true, false, true);
8481 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8490 vector
<DNSRecord
> ret
;
8491 /* first query does not require validation */
8492 sr
->setDNSSECValidationRequested(false);
8493 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8494 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8495 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8496 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8497 for (const auto& record
: ret
) {
8498 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8500 BOOST_CHECK_EQUAL(queriesCount
, 1);
8504 /* second one _does_ require validation */
8505 sr
->setDNSSECValidationRequested(true);
8506 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8507 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8508 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8509 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8510 for (const auto& record
: ret
) {
8511 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8513 BOOST_CHECK_EQUAL(queriesCount
, 3);
8516 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure
) {
8518 Validation is optional, and the first query does not ask for it,
8519 so the answer is negatively cached as Indeterminate.
8520 The second query asks for validation, answer should be marked as
8523 std::unique_ptr
<SyncRes
> sr
;
8526 setDNSSECValidation(sr
, DNSSECMode::Process
);
8529 const DNSName
target("com.");
8532 auto luaconfsCopy
= g_luaconfs
.getCopy();
8533 luaconfsCopy
.dsAnchors
.clear();
8534 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8535 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8536 g_luaconfs
.setState(luaconfsCopy
);
8538 size_t queriesCount
= 0;
8540 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
) {
8543 DNSName auth
= domain
;
8546 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8547 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8550 setLWResult(res
, RCode::NoError
, true, false, true);
8551 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8552 addRRSIG(keys
, res
->d_records
, domain
, 300);
8553 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
8554 addRRSIG(keys
, res
->d_records
, domain
, 1);
8561 vector
<DNSRecord
> ret
;
8562 /* first query does not require validation */
8563 sr
->setDNSSECValidationRequested(false);
8564 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8565 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8566 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8567 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8568 BOOST_CHECK_EQUAL(queriesCount
, 1);
8571 /* second one _does_ require validation */
8572 sr
->setDNSSECValidationRequested(true);
8573 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8574 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8575 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8576 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8577 BOOST_CHECK_EQUAL(queriesCount
, 4);
8580 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_insecure
) {
8582 Validation is optional, and the first query does not ask for it,
8583 so the answer is negatively cached as Indeterminate.
8584 The second query asks for validation, answer should be marked as
8587 std::unique_ptr
<SyncRes
> sr
;
8590 setDNSSECValidation(sr
, DNSSECMode::Process
);
8593 const DNSName
target("com.");
8596 auto luaconfsCopy
= g_luaconfs
.getCopy();
8597 luaconfsCopy
.dsAnchors
.clear();
8598 g_luaconfs
.setState(luaconfsCopy
);
8600 size_t queriesCount
= 0;
8602 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
) {
8605 DNSName auth
= domain
;
8608 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8609 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8612 setLWResult(res
, RCode::NoError
, true, false, true);
8613 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8620 vector
<DNSRecord
> ret
;
8621 /* first query does not require validation */
8622 sr
->setDNSSECValidationRequested(false);
8623 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8624 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8625 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8626 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8627 BOOST_CHECK_EQUAL(queriesCount
, 1);
8630 /* second one _does_ require validation */
8631 sr
->setDNSSECValidationRequested(true);
8632 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8633 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8634 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8635 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8636 BOOST_CHECK_EQUAL(queriesCount
, 1);
8639 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_bogus
) {
8641 Validation is optional, and the first query does not ask for it,
8642 so the answer is negatively cached as Indeterminate.
8643 The second query asks for validation, answer should be marked as
8646 std::unique_ptr
<SyncRes
> sr
;
8649 setDNSSECValidation(sr
, DNSSECMode::Process
);
8652 const DNSName
target("com.");
8655 auto luaconfsCopy
= g_luaconfs
.getCopy();
8656 luaconfsCopy
.dsAnchors
.clear();
8657 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8658 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8659 g_luaconfs
.setState(luaconfsCopy
);
8661 size_t queriesCount
= 0;
8663 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
) {
8666 DNSName auth
= domain
;
8669 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8670 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8673 setLWResult(res
, RCode::NoError
, true, false, true);
8674 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8675 addRRSIG(keys
, res
->d_records
, domain
, 300);
8683 vector
<DNSRecord
> ret
;
8684 /* first query does not require validation */
8685 sr
->setDNSSECValidationRequested(false);
8686 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8687 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8688 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8689 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8690 BOOST_CHECK_EQUAL(queriesCount
, 1);
8693 /* second one _does_ require validation */
8694 sr
->setDNSSECValidationRequested(true);
8695 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8696 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8697 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8698 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8699 BOOST_CHECK_EQUAL(queriesCount
, 4);
8702 BOOST_AUTO_TEST_CASE(test_lowercase_outgoing
) {
8703 g_lowercaseOutgoing
= true;
8704 std::unique_ptr
<SyncRes
> sr
;
8709 vector
<DNSName
> sentOutQnames
;
8711 const DNSName
target("WWW.POWERDNS.COM");
8712 const DNSName
cname("WWW.PowerDNS.org");
8714 sr
->setAsyncCallback([target
, cname
, &sentOutQnames
](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
) {
8716 sentOutQnames
.push_back(domain
);
8718 if (isRootServer(ip
)) {
8719 if (domain
== target
) {
8720 setLWResult(res
, 0, false, false, true);
8721 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
8722 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
8725 if (domain
== cname
) {
8726 setLWResult(res
, 0, false, false, true);
8727 addRecordToLW(res
, "powerdns.org.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
8728 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
8731 } else if (ip
== ComboAddress("192.0.2.1:53")) {
8732 if (domain
== target
) {
8733 setLWResult(res
, 0, true, false, false);
8734 addRecordToLW(res
, domain
, QType::CNAME
, cname
.toString());
8737 } else if (ip
== ComboAddress("192.0.2.2:53")) {
8738 if (domain
== cname
) {
8739 setLWResult(res
, 0, true, false, false);
8740 addRecordToLW(res
, domain
, QType::A
, "127.0.0.1");
8747 vector
<DNSRecord
> ret
;
8748 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8750 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8752 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8753 BOOST_CHECK_EQUAL(ret
[0].d_content
->getZoneRepresentation(), cname
.toString());
8755 BOOST_REQUIRE_EQUAL(sentOutQnames
.size(), 4);
8756 BOOST_CHECK_EQUAL(sentOutQnames
[0].toString(), target
.makeLowerCase().toString());
8757 BOOST_CHECK_EQUAL(sentOutQnames
[1].toString(), target
.makeLowerCase().toString());
8758 BOOST_CHECK_EQUAL(sentOutQnames
[2].toString(), cname
.makeLowerCase().toString());
8759 BOOST_CHECK_EQUAL(sentOutQnames
[3].toString(), cname
.makeLowerCase().toString());
8761 g_lowercaseOutgoing
= false;
8764 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo
) {
8765 std::unique_ptr
<SyncRes
> sr
;
8768 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8771 const DNSName
target("com.");
8772 testkeysset_t keys
, keys2
;
8774 auto luaconfsCopy
= g_luaconfs
.getCopy();
8775 luaconfsCopy
.dsAnchors
.clear();
8776 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8777 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8778 g_luaconfs
.setState(luaconfsCopy
);
8780 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
8781 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
8782 // But add the existing root key otherwise no RRSIG can be created
8783 auto rootkey
= keys
.find(g_rootdnsname
);
8784 keys2
.insert(*rootkey
);
8786 sr
->setAsyncCallback([target
, keys
, keys2
](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
) {
8787 DNSName auth
= domain
;
8789 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8790 if (domain
== target
) {
8791 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
8795 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8801 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
8802 BOOST_CHECK_EQUAL(state
, Secure
);
8803 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
8804 for (const auto& i
: ds
) {
8805 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
8809 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_all_sha
) {
8810 std::unique_ptr
<SyncRes
> sr
;
8813 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8816 const DNSName
target("com.");
8817 testkeysset_t keys
, keys2
, keys3
;
8819 auto luaconfsCopy
= g_luaconfs
.getCopy();
8820 luaconfsCopy
.dsAnchors
.clear();
8821 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8822 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8823 g_luaconfs
.setState(luaconfsCopy
);
8825 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
8826 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
8827 // But add the existing root key otherwise no RRSIG can be created
8828 auto rootkey
= keys
.find(g_rootdnsname
);
8829 keys2
.insert(*rootkey
);
8831 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys3
);
8832 // But add the existing root key otherwise no RRSIG can be created
8833 keys3
.insert(*rootkey
);
8835 sr
->setAsyncCallback([target
, keys
, keys2
, keys3
](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
) {
8836 DNSName auth
= domain
;
8838 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8839 if (domain
== target
) {
8840 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
8843 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
8847 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8853 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
8854 BOOST_CHECK_EQUAL(state
, Secure
);
8855 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
8856 for (const auto& i
: ds
) {
8857 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
8861 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_two_highest
) {
8862 std::unique_ptr
<SyncRes
> sr
;
8865 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8868 const DNSName
target("com.");
8869 testkeysset_t keys
, keys2
, keys3
;
8871 auto luaconfsCopy
= g_luaconfs
.getCopy();
8872 luaconfsCopy
.dsAnchors
.clear();
8873 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8874 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8875 g_luaconfs
.setState(luaconfsCopy
);
8877 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
8878 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys2
);
8879 // But add the existing root key otherwise no RRSIG can be created
8880 auto rootkey
= keys
.find(g_rootdnsname
);
8881 keys2
.insert(*rootkey
);
8883 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys3
);
8884 // But add the existing root key otherwise no RRSIG can be created
8885 keys3
.insert(*rootkey
);
8887 sr
->setAsyncCallback([target
, keys
, keys2
, keys3
](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
) {
8888 DNSName auth
= domain
;
8890 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8891 if (domain
== target
) {
8892 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
8895 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
8899 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8905 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
8906 BOOST_CHECK_EQUAL(state
, Secure
);
8907 BOOST_REQUIRE_EQUAL(ds
.size(), 2);
8908 for (const auto& i
: ds
) {
8909 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
8914 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha384_over_gost
) {
8915 std::unique_ptr
<SyncRes
> sr
;
8918 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8921 const DNSName
target("com.");
8922 testkeysset_t keys
, keys2
;
8924 auto luaconfsCopy
= g_luaconfs
.getCopy();
8925 luaconfsCopy
.dsAnchors
.clear();
8926 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8927 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys
);
8928 g_luaconfs
.setState(luaconfsCopy
);
8930 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
8931 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
8932 // But add the existing root key otherwise no RRSIG can be created
8933 auto rootkey
= keys
.find(g_rootdnsname
);
8934 keys2
.insert(*rootkey
);
8936 sr
->setAsyncCallback([target
, keys
, keys2
](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
) {
8937 DNSName auth
= domain
;
8939 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8940 if (domain
== target
) {
8941 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
8945 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8951 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
8952 BOOST_CHECK_EQUAL(state
, Secure
);
8953 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
8954 for (const auto& i
: ds
) {
8955 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
8959 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha256_over_gost
) {
8960 std::unique_ptr
<SyncRes
> sr
;
8963 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8966 const DNSName
target("com.");
8967 testkeysset_t keys
, keys2
;
8969 auto luaconfsCopy
= g_luaconfs
.getCopy();
8970 luaconfsCopy
.dsAnchors
.clear();
8971 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8972 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8973 g_luaconfs
.setState(luaconfsCopy
);
8975 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
8976 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
8977 // But add the existing root key otherwise no RRSIG can be created
8978 auto rootkey
= keys
.find(g_rootdnsname
);
8979 keys2
.insert(*rootkey
);
8981 sr
->setAsyncCallback([target
, keys
, keys2
](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
) {
8982 DNSName auth
= domain
;
8984 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8985 if (domain
== target
) {
8986 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
8990 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8996 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
8997 BOOST_CHECK_EQUAL(state
, Secure
);
8998 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
8999 for (const auto& i
: ds
) {
9000 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9004 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_gost_over_sha1
) {
9005 std::unique_ptr
<SyncRes
> sr
;
9008 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9011 const DNSName
target("com.");
9012 testkeysset_t keys
, keys2
;
9014 auto luaconfsCopy
= g_luaconfs
.getCopy();
9015 luaconfsCopy
.dsAnchors
.clear();
9016 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9017 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys
);
9018 g_luaconfs
.setState(luaconfsCopy
);
9020 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9021 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9022 // But add the existing root key otherwise no RRSIG can be created
9023 auto rootkey
= keys
.find(g_rootdnsname
);
9024 keys2
.insert(*rootkey
);
9026 sr
->setAsyncCallback([target
, keys
, keys2
](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
) {
9027 DNSName auth
= domain
;
9029 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9030 if (domain
== target
) {
9031 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9035 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9041 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9042 BOOST_CHECK_EQUAL(state
, Secure
);
9043 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9044 for (const auto& i
: ds
) {
9045 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::GOST
);
9048 #endif // HAVE_BOTAN110
9051 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
9053 - check out of band support
9059 BOOST_AUTO_TEST_SUITE_END()