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)
105 L
.disableSyslog(true);
108 L
.setLoglevel((Logger::Urgency
)(6)); // info and up
109 L
.toConsole(Logger::Info
);
112 L
.setLoglevel(Logger::None
);
113 L
.toConsole(Logger::Error
);
116 seedRandom("/dev/urandom");
119 t_RC
= std::unique_ptr
<MemRecursorCache
>(new MemRecursorCache());
121 SyncRes::s_maxqperq
= 50;
122 SyncRes::s_maxtotusec
= 1000*7000;
123 SyncRes::s_maxdepth
= 40;
124 SyncRes::s_maxnegttl
= 3600;
125 SyncRes::s_maxcachettl
= 86400;
126 SyncRes::s_packetcachettl
= 3600;
127 SyncRes::s_packetcacheservfailttl
= 60;
128 SyncRes::s_serverdownmaxfails
= 64;
129 SyncRes::s_serverdownthrottletime
= 60;
130 SyncRes::s_doIPv6
= true;
131 SyncRes::s_ecsipv4limit
= 24;
132 SyncRes::s_ecsipv6limit
= 56;
133 SyncRes::s_rootNXTrust
= true;
134 SyncRes::s_minimumTTL
= 0;
135 SyncRes::s_serverID
= "PowerDNS Unit Tests Server ID";
136 SyncRes::clearEDNSSubnets();
137 SyncRes::clearEDNSDomains();
138 SyncRes::clearDelegationOnly();
139 SyncRes::clearDontQuery();
141 SyncRes::clearNSSpeeds();
142 BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0);
143 SyncRes::clearEDNSStatuses();
144 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0);
145 SyncRes::clearThrottle();
146 BOOST_CHECK_EQUAL(SyncRes::getThrottledServersSize(), 0);
147 SyncRes::clearFailedServers();
148 BOOST_CHECK_EQUAL(SyncRes::getFailedServersSize(), 0);
150 auto luaconfsCopy
= g_luaconfs
.getCopy();
151 luaconfsCopy
.dfe
.clear();
152 luaconfsCopy
.dsAnchors
.clear();
153 for (const auto &dsRecord
: rootDSs
) {
154 auto ds
=unique_ptr
<DSRecordContent
>(dynamic_cast<DSRecordContent
*>(DSRecordContent::make(dsRecord
)));
155 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(*ds
);
157 luaconfsCopy
.negAnchors
.clear();
158 g_luaconfs
.setState(luaconfsCopy
);
160 g_dnssecmode
= DNSSECMode::Off
;
162 g_maxNSEC3Iterations
= 2500;
164 ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Unit Tests";
167 static void initSR(std::unique_ptr
<SyncRes
>& sr
, bool dnssec
=false, bool debug
=false, time_t fakeNow
=0)
171 now
.tv_sec
= fakeNow
;
175 Utility::gettimeofday(&now
, 0);
180 sr
= std::unique_ptr
<SyncRes
>(new SyncRes(now
));
181 sr
->setDoEDNS0(true);
183 sr
->setDoDNSSEC(dnssec
);
186 sr
->setLogMode(debug
== false ? SyncRes::LogNone
: SyncRes::Log
);
188 SyncRes::setDomainMap(std::make_shared
<SyncRes::domainmap_t
>());
189 SyncRes::clearNegCache();
192 static void setDNSSECValidation(std::unique_ptr
<SyncRes
>& sr
, const DNSSECMode
& mode
)
194 sr
->setDNSSECValidationRequested(true);
198 static void setLWResult(LWResult
* res
, int rcode
, bool aa
=false, bool tc
=false, bool edns
=false)
200 res
->d_rcode
= rcode
;
203 res
->d_haveEDNS
= edns
;
206 static void addRecordToLW(LWResult
* res
, const DNSName
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
=DNSResourceRecord::ANSWER
, uint32_t ttl
=60)
208 addRecordToList(res
->d_records
, name
, type
, content
, place
, ttl
);
211 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)
213 addRecordToLW(res
, DNSName(name
), type
, content
, place
, ttl
);
216 static bool isRootServer(const ComboAddress
& ip
)
219 for (size_t idx
= 0; idx
< rootIps4Count
; idx
++) {
220 if (ip
.toString() == rootIps4
[idx
]) {
226 for (size_t idx
= 0; idx
< rootIps6Count
; idx
++) {
227 if (ip
.toString() == rootIps6
[idx
]) {
236 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
)
238 time_t now
= time(nullptr);
239 DNSKEYRecordContent drc
= dpk
.getDNSKEY();
240 const std::shared_ptr
<DNSCryptoKeyEngine
> rc
= dpk
.getKey();
242 rrc
.d_type
= signQType
;
243 rrc
.d_labels
= signQName
.countLabels() - signQName
.isWildcard();
244 rrc
.d_originalttl
= signTTL
;
245 rrc
.d_siginception
= inception
? *inception
: (now
- 10);
246 rrc
.d_sigexpire
= now
+ sigValidity
;
247 rrc
.d_signer
= signer
;
249 rrc
.d_tag
= drc
.getTag();
250 rrc
.d_algorithm
= algo
? *algo
: drc
.d_algorithm
;
252 std::string msg
= getMessageForRRSET(signQName
, rrc
, toSign
);
254 rrc
.d_signature
= rc
->sign(msg
);
257 typedef std::unordered_map
<DNSName
, std::pair
<DNSSECPrivateKey
, DSRecordContent
> > testkeysset_t
;
259 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
)
261 if (records
.empty()) {
265 const auto it
= keys
.find(signer
);
266 if (it
== keys
.cend()) {
267 throw std::runtime_error("No DNSKEY found for " + signer
.toString() + ", unable to compute the requested RRSIG");
270 size_t recordsCount
= records
.size();
271 const DNSName
& name
= records
[recordsCount
-1].d_name
;
272 const uint16_t type
= records
[recordsCount
-1].d_type
;
274 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
275 for (const auto record
: records
) {
276 if (record
.d_name
== name
&& record
.d_type
== type
) {
277 recordcontents
.push_back(record
.d_content
);
281 RRSIGRecordContent rrc
;
282 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
);
284 rrc
.d_signature
[0] ^= 42;
288 rec
.d_type
= QType::RRSIG
;
289 rec
.d_place
= records
[recordsCount
-1].d_place
;
290 rec
.d_name
= records
[recordsCount
-1].d_name
;
291 rec
.d_ttl
= records
[recordsCount
-1].d_ttl
;
293 rec
.d_content
= std::make_shared
<RRSIGRecordContent
>(rrc
);
294 records
.push_back(rec
);
299 static void addDNSKEY(const testkeysset_t
& keys
, const DNSName
& signer
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
301 const auto it
= keys
.find(signer
);
302 if (it
== keys
.cend()) {
303 throw std::runtime_error("No DNSKEY found for " + signer
.toString());
307 rec
.d_place
= DNSResourceRecord::ANSWER
;
309 rec
.d_type
= QType::DNSKEY
;
312 rec
.d_content
= std::make_shared
<DNSKEYRecordContent
>(it
->second
.first
.getDNSKEY());
313 records
.push_back(rec
);
316 static bool addDS(const DNSName
& domain
, uint32_t ttl
, std::vector
<DNSRecord
>& records
, const testkeysset_t
& keys
, DNSResourceRecord::Place place
=DNSResourceRecord::AUTHORITY
)
318 const auto it
= keys
.find(domain
);
319 if (it
== keys
.cend()) {
325 rec
.d_type
= QType::DS
;
328 rec
.d_content
= std::make_shared
<DSRecordContent
>(it
->second
.second
);
330 records
.push_back(rec
);
334 static void addNSECRecordToLW(const DNSName
& domain
, const DNSName
& next
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
336 NSECRecordContent nrc
;
343 rec
.d_type
= QType::NSEC
;
344 rec
.d_content
= std::make_shared
<NSECRecordContent
>(nrc
);
345 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
347 records
.push_back(rec
);
350 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
)
352 NSEC3RecordContent nrc
;
355 nrc
.d_iterations
= iterations
;
357 nrc
.d_nexthash
= hashedNext
;
361 rec
.d_name
= hashedName
;
363 rec
.d_type
= QType::NSEC3
;
364 rec
.d_content
= std::make_shared
<NSEC3RecordContent
>(nrc
);
365 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
367 records
.push_back(rec
);
370 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)
372 static const std::string salt
= "deadbeef";
373 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
375 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, next
, salt
, iterations
, types
, ttl
, records
);
378 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)
380 static const std::string salt
= "deadbeef";
381 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
382 std::string
hashedNext(hashed
);
383 incrementHash(hashedNext
);
384 decrementHash(hashed
);
386 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, hashedNext
, salt
, iterations
, types
, ttl
, records
);
389 static void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
)
391 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(algo
));
392 dcke
->create((algo
<= 10) ? 2048 : dcke
->getBits());
393 DNSSECPrivateKey dpk
;
396 DSRecordContent ds
= makeDSFromDNSKey(name
, dpk
.getDNSKEY(), digest
);
397 keys
[name
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
,ds
);
400 static void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
, map
<DNSName
,dsmap_t
>& dsAnchors
)
402 generateKeyMaterial(name
, algo
, digest
, keys
);
403 dsAnchors
[name
].insert(keys
[name
].second
);
406 static int genericDSAndDNSKEYHandler(LWResult
* res
, const DNSName
& domain
, DNSName auth
, int type
, const testkeysset_t
& keys
, bool proveCut
=true)
408 if (type
== QType::DS
) {
411 setLWResult(res
, 0, true, false, true);
413 if (addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
)) {
414 addRRSIG(keys
, res
->d_records
, auth
, 300);
417 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
419 /* if the auth zone is signed, we need to provide a secure denial */
420 const auto it
= keys
.find(auth
);
421 if (it
!= keys
.cend()) {
423 addRRSIG(keys
, res
->d_records
, auth
, 300);
424 /* add a NSEC denying the DS */
425 std::set
<uint16_t> types
= { QType::NSEC
};
427 types
.insert(QType::NS
);
430 addNSECRecordToLW(domain
, DNSName("z") + domain
, types
, 600, res
->d_records
);
431 addRRSIG(keys
, res
->d_records
, auth
, 300);
438 if (type
== QType::DNSKEY
) {
439 setLWResult(res
, 0, true, false, true);
440 addDNSKEY(keys
, domain
, 300, res
->d_records
);
441 addRRSIG(keys
, res
->d_records
, domain
, 300);
450 BOOST_AUTO_TEST_SUITE(syncres_cc
)
452 BOOST_AUTO_TEST_CASE(test_root_primed
) {
453 std::unique_ptr
<SyncRes
> sr
;
458 const DNSName
target("a.root-servers.net.");
460 /* we are primed, we should be able to resolve A a.root-servers.net. without any query */
461 vector
<DNSRecord
> ret
;
462 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
463 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
464 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
465 BOOST_CHECK(ret
[0].d_type
== QType::A
);
466 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
469 res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
470 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
471 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
472 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
473 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
474 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
477 BOOST_AUTO_TEST_CASE(test_root_primed_ns
) {
478 std::unique_ptr
<SyncRes
> sr
;
482 const DNSName
target(".");
484 /* we are primed, but we should not be able to NS . without any query
485 because the . NS entry is not stored as authoritative */
487 size_t queriesCount
= 0;
489 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
) {
492 if (domain
== target
&& type
== QType::NS
) {
494 setLWResult(res
, 0, true, false, true);
495 char addr
[] = "a.root-servers.net.";
496 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
498 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
501 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
502 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
510 vector
<DNSRecord
> ret
;
511 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
512 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
513 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
514 BOOST_CHECK_EQUAL(queriesCount
, 1);
517 BOOST_AUTO_TEST_CASE(test_root_not_primed
) {
518 std::unique_ptr
<SyncRes
> sr
;
521 size_t queriesCount
= 0;
523 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
) {
526 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
527 setLWResult(res
, 0, true, false, true);
528 addRecordToLW(res
, g_rootdnsname
, QType::NS
, "a.root-servers.net.", DNSResourceRecord::ANSWER
, 3600);
529 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
530 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
538 /* we are not primed yet, so SyncRes will have to call primeHints()
539 then call getRootNS(), for which at least one of the root servers needs to answer */
540 vector
<DNSRecord
> ret
;
541 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
542 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
543 BOOST_CHECK_EQUAL(ret
.size(), 1);
544 BOOST_CHECK_EQUAL(queriesCount
, 2);
547 BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response
) {
548 std::unique_ptr
<SyncRes
> sr
;
550 std::set
<ComboAddress
> downServers
;
552 /* we are not primed yet, so SyncRes will have to call primeHints()
553 then call getRootNS(), for which at least one of the root servers needs to answer.
554 None will, so it should ServFail.
556 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
) {
558 downServers
.insert(ip
);
562 vector
<DNSRecord
> ret
;
563 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
564 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
565 BOOST_CHECK_EQUAL(ret
.size(), 0);
566 BOOST_CHECK(downServers
.size() > 0);
567 /* we explicitly refuse to mark the root servers down */
568 for (const auto& server
: downServers
) {
569 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
573 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback
) {
574 std::unique_ptr
<SyncRes
> sr
;
577 ComboAddress noEDNSServer
;
578 size_t queriesWithEDNS
= 0;
579 size_t queriesWithoutEDNS
= 0;
581 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
) {
582 if (EDNS0Level
!= 0) {
586 setLWResult(res
, RCode::FormErr
);
590 queriesWithoutEDNS
++;
592 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
593 setLWResult(res
, 0, true, false, false);
594 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
603 /* fake that the root NS doesn't handle EDNS, check that we fallback */
604 vector
<DNSRecord
> ret
;
605 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
606 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
607 BOOST_CHECK_EQUAL(ret
.size(), 1);
608 BOOST_CHECK_EQUAL(queriesWithEDNS
, 1);
609 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 1);
610 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 1);
611 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer
), SyncRes::EDNSStatus::NOEDNS
);
614 BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback
) {
615 std::unique_ptr
<SyncRes
> sr
;
618 size_t queriesWithEDNS
= 0;
619 size_t queriesWithoutEDNS
= 0;
621 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
) {
622 if (EDNS0Level
!= 0) {
624 setLWResult(res
, RCode::NotImp
);
628 queriesWithoutEDNS
++;
630 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
631 setLWResult(res
, 0, true, false, false);
632 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
641 /* fake that the NS doesn't handle EDNS, check that we fallback */
642 vector
<DNSRecord
> ret
;
643 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
644 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
645 BOOST_CHECK_EQUAL(ret
.size(), 1);
646 BOOST_CHECK_EQUAL(queriesWithEDNS
, 1);
647 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 1);
650 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
) {
651 std::unique_ptr
<SyncRes
> sr
;
654 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
) {
656 setLWResult(res
, 0, false, true, false);
659 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
660 setLWResult(res
, 0, true, false, false);
661 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
670 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
671 vector
<DNSRecord
> ret
;
672 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
673 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
676 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
) {
677 std::unique_ptr
<SyncRes
> sr
;
680 size_t tcpQueriesCount
= 0;
682 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
) {
684 setLWResult(res
, 0, true, true, false);
688 /* first TCP query is answered with a TC response */
690 if (tcpQueriesCount
== 1) {
691 setLWResult(res
, 0, true, true, false);
694 setLWResult(res
, 0, true, false, false);
697 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
703 vector
<DNSRecord
> ret
;
704 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
705 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
706 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2);
709 BOOST_AUTO_TEST_CASE(test_all_nss_down
) {
710 std::unique_ptr
<SyncRes
> sr
;
712 std::set
<ComboAddress
> downServers
;
716 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
) {
718 if (isRootServer(ip
)) {
719 setLWResult(res
, 0, false, false, true);
720 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
721 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
722 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
725 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
726 setLWResult(res
, 0, false, false, true);
727 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
728 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
729 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
730 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
731 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
732 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
736 downServers
.insert(ip
);
741 DNSName
target("powerdns.com.");
743 vector
<DNSRecord
> ret
;
744 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
745 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
746 BOOST_CHECK_EQUAL(ret
.size(), 0);
747 BOOST_CHECK_EQUAL(downServers
.size(), 4);
749 for (const auto& server
: downServers
) {
750 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
751 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
755 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
) {
756 std::unique_ptr
<SyncRes
> sr
;
758 std::set
<ComboAddress
> downServers
;
762 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
) {
764 if (isRootServer(ip
)) {
765 setLWResult(res
, 0, false, false, true);
766 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
767 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
768 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
771 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
772 setLWResult(res
, 0, false, false, true);
773 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
774 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
775 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
776 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
777 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
778 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
782 downServers
.insert(ip
);
787 /* exact same test than the previous one, except instead of a time out we fake a network error */
788 DNSName
target("powerdns.com.");
790 vector
<DNSRecord
> ret
;
791 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
792 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
793 BOOST_CHECK_EQUAL(ret
.size(), 0);
794 BOOST_CHECK_EQUAL(downServers
.size(), 4);
796 for (const auto& server
: downServers
) {
797 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
798 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
802 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
) {
803 std::unique_ptr
<SyncRes
> sr
;
808 DNSName
target("www.powerdns.com.");
810 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
) {
812 if (isRootServer(ip
)) {
813 setLWResult(res
, 0, false, false, true);
814 if (domain
== target
) {
815 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
816 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
817 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
818 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
820 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
821 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
822 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
823 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
824 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
828 else if (ip
== ComboAddress("192.0.2.3:53")) {
829 setLWResult(res
, 0, true, false, true);
830 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
831 if (type
== QType::A
) {
832 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
834 else if (type
== QType::AAAA
) {
835 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
838 else if (domain
== target
) {
839 if (type
== QType::A
) {
840 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
842 else if (type
== QType::AAAA
) {
843 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
851 vector
<DNSRecord
> ret
;
852 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
853 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
854 BOOST_CHECK_EQUAL(ret
.size(), 1);
857 BOOST_AUTO_TEST_CASE(test_os_limit_errors
) {
858 std::unique_ptr
<SyncRes
> sr
;
860 std::set
<ComboAddress
> downServers
;
864 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
) {
866 if (isRootServer(ip
)) {
867 setLWResult(res
, 0, false, false, true);
868 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
869 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
870 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
873 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
874 setLWResult(res
, 0, false, false, true);
875 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
876 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
877 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
878 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
879 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
880 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
884 if (downServers
.size() < 3) {
885 /* only the last one will answer */
886 downServers
.insert(ip
);
890 setLWResult(res
, 0, true, false, true);
891 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
897 DNSName
target("powerdns.com.");
899 vector
<DNSRecord
> ret
;
900 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
901 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
902 BOOST_CHECK_EQUAL(ret
.size(), 1);
903 BOOST_CHECK_EQUAL(downServers
.size(), 3);
905 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
906 for (const auto& server
: downServers
) {
907 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
908 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
912 BOOST_AUTO_TEST_CASE(test_glued_referral
) {
913 std::unique_ptr
<SyncRes
> sr
;
918 const DNSName
target("powerdns.com.");
920 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
) {
921 /* this will cause issue with qname minimization if we ever implement it */
922 if (domain
!= target
) {
926 if (isRootServer(ip
)) {
927 setLWResult(res
, 0, false, false, true);
928 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
929 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
930 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
933 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
934 setLWResult(res
, 0, false, false, true);
935 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
936 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
937 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
938 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
939 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
940 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
943 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")) {
944 setLWResult(res
, 0, true, false, true);
945 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
953 vector
<DNSRecord
> ret
;
954 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
955 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
956 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
957 BOOST_CHECK(ret
[0].d_type
== QType::A
);
958 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
961 BOOST_AUTO_TEST_CASE(test_glueless_referral
) {
962 std::unique_ptr
<SyncRes
> sr
;
967 const DNSName
target("powerdns.com.");
969 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
) {
971 if (isRootServer(ip
)) {
972 setLWResult(res
, 0, false, false, true);
974 if (domain
.isPartOf(DNSName("com."))) {
975 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
976 } else if (domain
.isPartOf(DNSName("org."))) {
977 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
980 setLWResult(res
, RCode::NXDomain
, false, false, true);
984 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
985 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
988 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
989 if (domain
== target
) {
990 setLWResult(res
, 0, false, false, true);
991 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
992 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
995 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
996 setLWResult(res
, 0, true, false, true);
997 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
998 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1001 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1002 setLWResult(res
, 0, true, false, true);
1003 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1004 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1008 setLWResult(res
, RCode::NXDomain
, false, false, true);
1011 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")) {
1012 setLWResult(res
, 0, true, false, true);
1013 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1021 vector
<DNSRecord
> ret
;
1022 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1023 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1024 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1025 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1026 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1029 BOOST_AUTO_TEST_CASE(test_edns_submask_by_domain
) {
1030 std::unique_ptr
<SyncRes
> sr
;
1035 const DNSName
target("powerdns.com.");
1036 SyncRes::addEDNSDomain(target
);
1038 EDNSSubnetOpts incomingECS
;
1039 incomingECS
.source
= Netmask("192.0.2.128/32");
1040 sr
->setIncomingECSFound(true);
1041 sr
->setIncomingECS(incomingECS
);
1043 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
) {
1045 BOOST_REQUIRE(srcmask
);
1046 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1050 vector
<DNSRecord
> ret
;
1051 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1052 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1055 BOOST_AUTO_TEST_CASE(test_edns_submask_by_addr
) {
1056 std::unique_ptr
<SyncRes
> sr
;
1061 const DNSName
target("powerdns.com.");
1062 SyncRes::addEDNSSubnet(Netmask("192.0.2.1/32"));
1064 EDNSSubnetOpts incomingECS
;
1065 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1066 sr
->setIncomingECSFound(true);
1067 sr
->setIncomingECS(incomingECS
);
1069 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
) {
1071 if (isRootServer(ip
)) {
1072 BOOST_REQUIRE(!srcmask
);
1074 setLWResult(res
, 0, false, false, true);
1075 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1076 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1078 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1080 BOOST_REQUIRE(srcmask
);
1081 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1083 setLWResult(res
, 0, true, false, false);
1084 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1091 vector
<DNSRecord
> ret
;
1092 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1093 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1094 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1095 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1096 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1099 BOOST_AUTO_TEST_CASE(test_following_cname
) {
1100 std::unique_ptr
<SyncRes
> sr
;
1105 const DNSName
target("cname.powerdns.com.");
1106 const DNSName
cnameTarget("cname-target.powerdns.com");
1108 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
) {
1110 if (isRootServer(ip
)) {
1111 setLWResult(res
, 0, false, false, true);
1112 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1113 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1115 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1117 if (domain
== target
) {
1118 setLWResult(res
, 0, true, false, false);
1119 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1122 else if (domain
== cnameTarget
) {
1123 setLWResult(res
, 0, true, false, false);
1124 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1133 vector
<DNSRecord
> ret
;
1134 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1135 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1136 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1137 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1138 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1139 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1140 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1143 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
) {
1144 std::unique_ptr
<SyncRes
> sr
;
1149 const DNSName
target("cname.powerdns.com.");
1150 const DNSName
cnameTarget("cname-target.powerdns.com");
1152 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
) {
1154 if (isRootServer(ip
)) {
1155 setLWResult(res
, 0, false, false, true);
1156 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1157 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1159 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1161 if (domain
== target
) {
1162 setLWResult(res
, RCode::NXDomain
, true, false, false);
1163 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1164 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1165 } else if (domain
== cnameTarget
) {
1166 setLWResult(res
, RCode::NXDomain
, true, false, false);
1167 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1177 vector
<DNSRecord
> ret
;
1178 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1179 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1180 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1181 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1182 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1183 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1185 /* a second time, to check the cache */
1187 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1188 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1189 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1190 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1191 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1192 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1195 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
) {
1196 std::unique_ptr
<SyncRes
> sr
;
1201 /* In this test we directly get the NS server for cname.powerdns.com.,
1202 and we don't know whether it's also authoritative for
1203 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1204 the additional A record for cname-target.powerdns.com. */
1205 const DNSName
target("cname.powerdns.com.");
1206 const DNSName
cnameTarget("cname-target.powerdns.com");
1208 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
) {
1210 if (isRootServer(ip
)) {
1212 setLWResult(res
, 0, false, false, true);
1214 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1215 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1217 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1219 if (domain
== target
) {
1220 setLWResult(res
, 0, true, false, false);
1221 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1222 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1224 } else if (domain
== cnameTarget
) {
1225 setLWResult(res
, 0, true, false, false);
1226 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1236 vector
<DNSRecord
> ret
;
1237 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1238 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1239 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1240 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1241 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1242 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1243 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1244 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1245 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1248 BOOST_AUTO_TEST_CASE(test_cname_loop
) {
1249 std::unique_ptr
<SyncRes
> sr
;
1255 const DNSName
target("cname.powerdns.com.");
1257 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
) {
1261 if (isRootServer(ip
)) {
1263 setLWResult(res
, 0, false, false, true);
1264 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1265 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1267 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1269 if (domain
== target
) {
1270 setLWResult(res
, 0, true, false, false);
1271 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1281 vector
<DNSRecord
> ret
;
1282 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1283 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1284 BOOST_CHECK_GT(ret
.size(), 0);
1285 BOOST_CHECK_EQUAL(count
, 2);
1288 BOOST_AUTO_TEST_CASE(test_cname_depth
) {
1289 std::unique_ptr
<SyncRes
> sr
;
1295 const DNSName
target("cname.powerdns.com.");
1297 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
) {
1299 if (isRootServer(ip
)) {
1301 setLWResult(res
, 0, false, false, true);
1302 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1303 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1305 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1307 setLWResult(res
, 0, true, false, false);
1308 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(depth
) + "-cname.powerdns.com");
1316 vector
<DNSRecord
> ret
;
1317 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1318 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1319 BOOST_CHECK_EQUAL(ret
.size(), depth
);
1320 /* we have an arbitrary limit at 10 when following a CNAME chain */
1321 BOOST_CHECK_EQUAL(depth
, 10 + 2);
1324 BOOST_AUTO_TEST_CASE(test_time_limit
) {
1325 std::unique_ptr
<SyncRes
> sr
;
1331 const DNSName
target("cname.powerdns.com.");
1333 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
) {
1337 if (isRootServer(ip
)) {
1338 setLWResult(res
, 0, false, false, true);
1339 /* Pretend that this query took 2000 ms */
1342 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1343 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1345 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1347 setLWResult(res
, 0, true, false, false);
1348 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1355 /* Set the maximum time to 1 ms */
1356 SyncRes::s_maxtotusec
= 1000;
1359 vector
<DNSRecord
> ret
;
1360 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1363 catch(const ImmediateServFailException
& e
) {
1365 BOOST_CHECK_EQUAL(queries
, 1);
1368 BOOST_AUTO_TEST_CASE(test_referral_depth
) {
1369 std::unique_ptr
<SyncRes
> sr
;
1375 const DNSName
target("www.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
)) {
1382 setLWResult(res
, 0, false, false, true);
1384 if (domain
== DNSName("www.powerdns.com.")) {
1385 addRecordToLW(res
, domain
, QType::NS
, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1387 else if (domain
== DNSName("ns.powerdns.com.")) {
1388 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1390 else if (domain
== DNSName("ns1.powerdns.org.")) {
1391 addRecordToLW(res
, domain
, QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1393 else if (domain
== DNSName("ns2.powerdns.org.")) {
1394 addRecordToLW(res
, domain
, QType::NS
, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1396 else if (domain
== DNSName("ns3.powerdns.org.")) {
1397 addRecordToLW(res
, domain
, QType::NS
, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1399 else if (domain
== DNSName("ns4.powerdns.org.")) {
1400 addRecordToLW(res
, domain
, QType::NS
, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1401 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::AUTHORITY
, 172800);
1405 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1407 setLWResult(res
, 0, true, false, false);
1408 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1415 /* Set the maximum depth low */
1416 SyncRes::s_maxdepth
= 10;
1419 vector
<DNSRecord
> ret
;
1420 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1423 catch(const ImmediateServFailException
& e
) {
1427 BOOST_AUTO_TEST_CASE(test_cname_qperq
) {
1428 std::unique_ptr
<SyncRes
> sr
;
1434 const DNSName
target("cname.powerdns.com.");
1436 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
) {
1440 if (isRootServer(ip
)) {
1442 setLWResult(res
, 0, false, false, true);
1443 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1444 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1446 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1448 setLWResult(res
, 0, true, false, false);
1449 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(queries
) + "-cname.powerdns.com");
1456 /* Set the maximum number of questions very low */
1457 SyncRes::s_maxqperq
= 5;
1460 vector
<DNSRecord
> ret
;
1461 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1464 catch(const ImmediateServFailException
& e
) {
1465 BOOST_CHECK_EQUAL(queries
, SyncRes::s_maxqperq
);
1469 BOOST_AUTO_TEST_CASE(test_throttled_server
) {
1470 std::unique_ptr
<SyncRes
> sr
;
1475 const DNSName
target("throttled.powerdns.com.");
1476 const ComboAddress
ns("192.0.2.1:53");
1477 size_t queriesToNS
= 0;
1479 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
) {
1481 if (isRootServer(ip
)) {
1483 setLWResult(res
, 0, false, false, true);
1484 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1485 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1487 } else if (ip
== ns
) {
1491 setLWResult(res
, 0, true, false, false);
1492 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1500 /* mark ns as down */
1501 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, 10000);
1503 vector
<DNSRecord
> ret
;
1504 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1505 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1506 BOOST_CHECK_EQUAL(ret
.size(), 0);
1507 /* we should not have sent any queries to ns */
1508 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1511 BOOST_AUTO_TEST_CASE(test_throttled_server_count
) {
1512 std::unique_ptr
<SyncRes
> sr
;
1517 const ComboAddress
ns("192.0.2.1:53");
1519 const size_t blocks
= 10;
1520 /* mark ns as down for 'blocks' queries */
1521 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, blocks
);
1523 for (size_t idx
= 0; idx
< blocks
; idx
++) {
1524 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1527 /* we have been throttled 'blocks' times, we should not be throttled anymore */
1528 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1531 BOOST_AUTO_TEST_CASE(test_throttled_server_time
) {
1532 std::unique_ptr
<SyncRes
> sr
;
1537 const ComboAddress
ns("192.0.2.1:53");
1539 const size_t seconds
= 1;
1540 /* mark ns as down for 'seconds' seconds */
1541 SyncRes::doThrottle(time(nullptr), ns
, seconds
, 10000);
1543 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1547 /* we should not be throttled anymore */
1548 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1551 BOOST_AUTO_TEST_CASE(test_dont_query_server
) {
1552 std::unique_ptr
<SyncRes
> sr
;
1557 const DNSName
target("throttled.powerdns.com.");
1558 const ComboAddress
ns("192.0.2.1:53");
1559 size_t queriesToNS
= 0;
1561 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
) {
1563 if (isRootServer(ip
)) {
1565 setLWResult(res
, 0, false, false, true);
1566 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1567 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1569 } else if (ip
== ns
) {
1573 setLWResult(res
, 0, true, false, false);
1574 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1582 /* prevent querying this NS */
1583 SyncRes::addDontQuery(Netmask(ns
));
1585 vector
<DNSRecord
> ret
;
1586 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1587 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1588 BOOST_CHECK_EQUAL(ret
.size(), 0);
1589 /* we should not have sent any queries to ns */
1590 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1593 BOOST_AUTO_TEST_CASE(test_root_nx_trust
) {
1594 std::unique_ptr
<SyncRes
> sr
;
1599 const DNSName
target1("powerdns.com.");
1600 const DNSName
target2("notpowerdns.com.");
1601 const ComboAddress
ns("192.0.2.1:53");
1602 size_t queriesCount
= 0;
1604 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
) {
1608 if (isRootServer(ip
)) {
1610 if (domain
== target1
) {
1611 setLWResult(res
, RCode::NXDomain
, true, false, true);
1612 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1615 setLWResult(res
, 0, true, false, true);
1616 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1617 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1621 } else if (ip
== ns
) {
1623 setLWResult(res
, 0, true, false, false);
1624 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1632 vector
<DNSRecord
> ret
;
1633 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1634 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1635 BOOST_CHECK_EQUAL(ret
.size(), 1);
1636 /* one for target1 and one for the entire TLD */
1637 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1640 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1641 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1642 BOOST_CHECK_EQUAL(ret
.size(), 1);
1643 /* one for target1 and one for the entire TLD */
1644 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1646 /* we should have sent only one query */
1647 BOOST_CHECK_EQUAL(queriesCount
, 1);
1650 BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific
) {
1651 std::unique_ptr
<SyncRes
> sr
;
1653 initSR(sr
, true, false);
1657 const DNSName
target1("powerdns.com.");
1658 const DNSName
target2("notpowerdns.com.");
1659 const ComboAddress
ns("192.0.2.1:53");
1660 size_t queriesCount
= 0;
1662 /* This time the root denies target1 with a "com." SOA instead of a "." one.
1663 We should add target1 to the negcache, but not "com.". */
1665 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
) {
1669 if (isRootServer(ip
)) {
1671 if (domain
== target1
) {
1672 setLWResult(res
, RCode::NXDomain
, true, false, true);
1673 addRecordToLW(res
, "com.", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1676 setLWResult(res
, 0, true, false, true);
1677 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1678 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1682 } else if (ip
== ns
) {
1684 setLWResult(res
, 0, true, false, false);
1685 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1693 vector
<DNSRecord
> ret
;
1694 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1695 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1696 BOOST_CHECK_EQUAL(ret
.size(), 1);
1698 /* even with root-nx-trust on and a NX answer from the root,
1699 we should not have cached the entire TLD this time. */
1700 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1703 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1704 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1705 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1706 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1707 BOOST_CHECK_EQUAL(ret
[0].d_name
, target2
);
1708 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress("192.0.2.2"));
1710 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1712 BOOST_CHECK_EQUAL(queriesCount
, 3);
1715 BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust
) {
1716 std::unique_ptr
<SyncRes
> sr
;
1721 const DNSName
target1("powerdns.com.");
1722 const DNSName
target2("notpowerdns.com.");
1723 const ComboAddress
ns("192.0.2.1:53");
1724 size_t queriesCount
= 0;
1726 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
) {
1730 if (isRootServer(ip
)) {
1732 if (domain
== target1
) {
1733 setLWResult(res
, RCode::NXDomain
, true, false, true);
1734 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1737 setLWResult(res
, 0, true, false, true);
1738 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1739 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1743 } else if (ip
== ns
) {
1745 setLWResult(res
, 0, true, false, false);
1746 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1754 SyncRes::s_rootNXTrust
= false;
1756 vector
<DNSRecord
> ret
;
1757 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1758 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1759 BOOST_CHECK_EQUAL(ret
.size(), 1);
1760 /* one for target1 */
1761 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1764 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1765 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1766 BOOST_CHECK_EQUAL(ret
.size(), 1);
1767 /* one for target1 */
1768 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1770 /* we should have sent three queries */
1771 BOOST_CHECK_EQUAL(queriesCount
, 3);
1774 BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response
) {
1775 std::unique_ptr
<SyncRes
> sr
;
1780 const DNSName
target("www.powerdns.com.");
1781 const DNSName
cnameTarget("cname.powerdns.com.");
1783 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
1785 EDNSSubnetOpts incomingECS
;
1786 incomingECS
.source
= Netmask("192.0.2.128/32");
1787 sr
->setIncomingECSFound(true);
1788 sr
->setIncomingECS(incomingECS
);
1790 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
) {
1792 BOOST_REQUIRE(srcmask
);
1793 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1795 if (isRootServer(ip
)) {
1796 setLWResult(res
, 0, false, false, true);
1797 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1798 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1801 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1802 if (domain
== target
) {
1803 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
1804 setLWResult(res
, RCode::NXDomain
, true, false, true);
1805 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1806 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1808 else if (domain
== cnameTarget
) {
1809 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
1810 but we might if we still chase the CNAME. */
1811 setLWResult(res
, RCode::NXDomain
, true, false, true);
1812 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1821 vector
<DNSRecord
> ret
;
1822 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1823 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1824 BOOST_CHECK_EQUAL(ret
.size(), 2);
1825 /* no negative cache entry because the response was variable */
1826 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0);
1829 BOOST_AUTO_TEST_CASE(test_ns_speed
) {
1830 std::unique_ptr
<SyncRes
> sr
;
1835 const DNSName
target("powerdns.com.");
1837 std::map
<ComboAddress
, uint64_t> nsCounts
;
1839 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
) {
1841 if (isRootServer(ip
)) {
1842 setLWResult(res
, 0, false, false, true);
1843 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1844 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1845 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1847 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1848 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1849 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1850 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 3600);
1851 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 3600);
1852 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 3600);
1858 if (ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("192.0.2.2:53")) {
1859 BOOST_CHECK_LT(nsCounts
.size(), 3);
1861 /* let's time out on pdns-public-ns2.powerdns.com. */
1864 else if (ip
== ComboAddress("192.0.2.1:53")) {
1865 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1867 setLWResult(res
, 0, true, false, true);
1868 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1879 gettimeofday(&now
, 0);
1881 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1882 then pdns-public-ns1.powerdns.com. on IPv4 */
1883 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now
);
1884 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now
);
1885 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now
);
1886 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now
);
1887 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now
);
1888 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now
);
1890 vector
<DNSRecord
> ret
;
1891 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1892 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1893 BOOST_CHECK_EQUAL(ret
.size(), 1);
1894 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1895 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.1:53")], 1);
1896 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.2:53")], 1);
1897 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("[2001:DB8::2]:53")], 1);
1900 BOOST_AUTO_TEST_CASE(test_flawed_nsset
) {
1901 std::unique_ptr
<SyncRes
> sr
;
1906 const DNSName
target("powerdns.com.");
1908 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
) {
1910 if (isRootServer(ip
)) {
1911 setLWResult(res
, 0, false, false, true);
1912 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1914 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1917 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1918 setLWResult(res
, 0, true, false, true);
1919 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1926 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1927 time_t now
= time(nullptr);
1928 std::vector
<DNSRecord
> records
;
1929 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1930 addRecordToList(records
, target
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, now
+ 3600);
1932 t_RC
->replace(now
, target
, QType(QType::NS
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1934 vector
<DNSRecord
> ret
;
1935 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1936 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1937 BOOST_CHECK_EQUAL(ret
.size(), 1);
1940 BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset
) {
1941 std::unique_ptr
<SyncRes
> sr
;
1946 const DNSName
target("powerdns.com.");
1947 size_t queriesCount
= 0;
1949 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
) {
1953 if (isRootServer(ip
) && domain
== target
) {
1954 setLWResult(res
, 0, false, false, true);
1955 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1956 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1958 } else if (domain
== DNSName("pdns-public-ns2.powerdns.com.") || domain
== DNSName("pdns-public-ns3.powerdns.com.")){
1959 setLWResult(res
, 0, true, false, true);
1960 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1967 vector
<DNSRecord
> ret
;
1968 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1969 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1970 BOOST_CHECK_EQUAL(ret
.size(), 0);
1971 /* one query to get NSs, then A and AAAA for each NS */
1972 BOOST_CHECK_EQUAL(queriesCount
, 5);
1975 BOOST_AUTO_TEST_CASE(test_cache_hit
) {
1976 std::unique_ptr
<SyncRes
> sr
;
1981 const DNSName
target("powerdns.com.");
1983 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
) {
1988 /* we populate the cache with eveything we need */
1989 time_t now
= time(nullptr);
1990 std::vector
<DNSRecord
> records
;
1991 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1993 addRecordToList(records
, target
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, now
+ 3600);
1994 t_RC
->replace(now
, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1996 vector
<DNSRecord
> ret
;
1997 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1998 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1999 BOOST_CHECK_EQUAL(ret
.size(), 1);
2002 BOOST_AUTO_TEST_CASE(test_no_rd
) {
2003 std::unique_ptr
<SyncRes
> sr
;
2008 const DNSName
target("powerdns.com.");
2009 size_t queriesCount
= 0;
2013 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
) {
2019 vector
<DNSRecord
> ret
;
2020 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2021 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2022 BOOST_CHECK_EQUAL(ret
.size(), 0);
2023 BOOST_CHECK_EQUAL(queriesCount
, 0);
2026 BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl
) {
2027 std::unique_ptr
<SyncRes
> sr
;
2032 const DNSName
target("cachettl.powerdns.com.");
2033 const ComboAddress
ns("192.0.2.1:53");
2035 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
) {
2037 if (isRootServer(ip
)) {
2039 setLWResult(res
, 0, false, false, true);
2040 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2041 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 7200);
2043 } else if (ip
== ns
) {
2045 setLWResult(res
, 0, true, false, false);
2046 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
2054 const time_t now
= time(nullptr);
2055 SyncRes::s_minimumTTL
= 60;
2056 SyncRes::s_maxcachettl
= 3600;
2058 vector
<DNSRecord
> ret
;
2059 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2060 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2061 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2062 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumTTL
);
2064 const ComboAddress who
;
2065 vector
<DNSRecord
> cached
;
2066 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
2067 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2068 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2069 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
2072 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
2073 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2074 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2075 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
2078 BOOST_AUTO_TEST_CASE(test_cache_expired_ttl
) {
2079 std::unique_ptr
<SyncRes
> sr
;
2084 const DNSName
target("powerdns.com.");
2086 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
) {
2088 if (isRootServer(ip
)) {
2089 setLWResult(res
, 0, false, false, true);
2090 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2092 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2095 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2096 setLWResult(res
, 0, true, false, true);
2097 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2104 /* we populate the cache with entries that expired 60s ago*/
2105 time_t now
= time(nullptr);
2106 std::vector
<DNSRecord
> records
;
2107 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
2108 addRecordToList(records
, target
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, now
- 60);
2110 t_RC
->replace(now
- 3600, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
2112 vector
<DNSRecord
> ret
;
2113 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2114 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2115 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2116 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
2117 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
2120 BOOST_AUTO_TEST_CASE(test_delegation_only
) {
2121 std::unique_ptr
<SyncRes
> sr
;
2126 /* Thanks, Verisign */
2127 SyncRes::addDelegationOnly(DNSName("com."));
2128 SyncRes::addDelegationOnly(DNSName("net."));
2130 const DNSName
target("nx-powerdns.com.");
2132 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
) {
2134 if (isRootServer(ip
)) {
2135 setLWResult(res
, 0, false, false, true);
2136 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2137 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2139 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2141 setLWResult(res
, 0, true, false, true);
2142 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2149 vector
<DNSRecord
> ret
;
2150 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2151 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2152 BOOST_CHECK_EQUAL(ret
.size(), 0);
2155 BOOST_AUTO_TEST_CASE(test_unauth_any
) {
2156 std::unique_ptr
<SyncRes
> sr
;
2161 const DNSName
target("powerdns.com.");
2163 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
) {
2165 if (isRootServer(ip
)) {
2166 setLWResult(res
, 0, false, false, true);
2167 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2168 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2170 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2172 setLWResult(res
, 0, false, false, true);
2173 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2180 vector
<DNSRecord
> ret
;
2181 int res
= sr
->beginResolve(target
, QType(QType::ANY
), QClass::IN
, ret
);
2182 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2183 BOOST_CHECK_EQUAL(ret
.size(), 0);
2186 BOOST_AUTO_TEST_CASE(test_no_data
) {
2187 std::unique_ptr
<SyncRes
> sr
;
2192 const DNSName
target("powerdns.com.");
2194 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
) {
2196 setLWResult(res
, 0, true, false, true);
2200 vector
<DNSRecord
> ret
;
2201 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2202 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2203 BOOST_CHECK_EQUAL(ret
.size(), 0);
2206 BOOST_AUTO_TEST_CASE(test_skip_opt_any
) {
2207 std::unique_ptr
<SyncRes
> sr
;
2212 const DNSName
target("powerdns.com.");
2214 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
) {
2216 setLWResult(res
, 0, true, false, true);
2217 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2218 addRecordToLW(res
, domain
, QType::ANY
, "0 0");
2219 addRecordToLW(res
, domain
, QType::OPT
, "");
2223 vector
<DNSRecord
> ret
;
2224 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2225 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2226 BOOST_CHECK_EQUAL(ret
.size(), 1);
2229 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec
) {
2230 std::unique_ptr
<SyncRes
> sr
;
2235 const DNSName
target("powerdns.com.");
2237 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
) {
2239 setLWResult(res
, 0, true, false, true);
2240 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2241 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2242 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2243 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2244 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2248 vector
<DNSRecord
> ret
;
2249 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2250 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2251 BOOST_CHECK_EQUAL(ret
.size(), 1);
2254 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec
) {
2255 std::unique_ptr
<SyncRes
> sr
;
2260 const DNSName
target("powerdns.com.");
2262 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
) {
2264 setLWResult(res
, 0, true, false, true);
2265 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2266 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2267 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2268 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2269 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2273 vector
<DNSRecord
> ret
;
2274 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2275 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2276 BOOST_CHECK_EQUAL(ret
.size(), 4);
2279 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec
) {
2280 std::unique_ptr
<SyncRes
> sr
;
2285 const DNSName
target("powerdns.com.");
2287 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
) {
2289 setLWResult(res
, RCode::NXDomain
, true, false, true);
2290 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2291 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2292 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2293 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2294 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2298 vector
<DNSRecord
> ret
;
2299 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2300 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2301 BOOST_CHECK_EQUAL(ret
.size(), 1);
2304 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec
) {
2305 std::unique_ptr
<SyncRes
> sr
;
2310 const DNSName
target("powerdns.com.");
2312 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
) {
2314 setLWResult(res
, RCode::NXDomain
, true, false, true);
2315 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2316 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2317 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2318 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2319 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2323 vector
<DNSRecord
> ret
;
2324 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2325 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2326 BOOST_CHECK_EQUAL(ret
.size(), 4);
2329 BOOST_AUTO_TEST_CASE(test_qclass_none
) {
2330 std::unique_ptr
<SyncRes
> sr
;
2335 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
2336 size_t queriesCount
= 0;
2338 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
) {
2344 const DNSName
target("powerdns.com.");
2345 vector
<DNSRecord
> ret
;
2346 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::NONE
, ret
);
2347 BOOST_CHECK_EQUAL(res
, -1);
2348 BOOST_CHECK_EQUAL(ret
.size(), 0);
2349 BOOST_CHECK_EQUAL(queriesCount
, 0);
2352 BOOST_AUTO_TEST_CASE(test_special_types
) {
2353 std::unique_ptr
<SyncRes
> sr
;
2358 /* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
2359 size_t queriesCount
= 0;
2361 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
) {
2363 cerr
<<"asyncresolve called to ask "<<ip
.toStringWithPort()<<" about "<<domain
.toString()<<" / "<<QType(type
).getName()<<" over "<<(doTCP
? "TCP" : "UDP")<<" (rd: "<<sendRDQuery
<<", EDNS0 level: "<<EDNS0Level
<<")"<<endl
;
2368 const DNSName
target("powerdns.com.");
2369 vector
<DNSRecord
> ret
;
2370 int res
= sr
->beginResolve(target
, QType(QType::AXFR
), QClass::IN
, ret
);
2371 BOOST_CHECK_EQUAL(res
, -1);
2372 BOOST_CHECK_EQUAL(ret
.size(), 0);
2373 BOOST_CHECK_EQUAL(queriesCount
, 0);
2375 res
= sr
->beginResolve(target
, QType(QType::IXFR
), QClass::IN
, ret
);
2376 BOOST_CHECK_EQUAL(res
, -1);
2377 BOOST_CHECK_EQUAL(ret
.size(), 0);
2378 BOOST_CHECK_EQUAL(queriesCount
, 0);
2380 res
= sr
->beginResolve(target
, QType(QType::RRSIG
), QClass::IN
, ret
);
2381 BOOST_CHECK_EQUAL(res
, -1);
2382 BOOST_CHECK_EQUAL(ret
.size(), 0);
2383 BOOST_CHECK_EQUAL(queriesCount
, 0);
2385 res
= sr
->beginResolve(target
, QType(QType::NSEC3
), QClass::IN
, ret
);
2386 BOOST_CHECK_EQUAL(res
, -1);
2387 BOOST_CHECK_EQUAL(ret
.size(), 0);
2388 BOOST_CHECK_EQUAL(queriesCount
, 0);
2391 BOOST_AUTO_TEST_CASE(test_special_names
) {
2392 std::unique_ptr
<SyncRes
> sr
;
2397 /* special names should be handled internally */
2399 size_t queriesCount
= 0;
2401 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
) {
2407 vector
<DNSRecord
> ret
;
2408 int res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
2409 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2410 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2411 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2412 BOOST_CHECK_EQUAL(queriesCount
, 0);
2415 res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
2416 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2417 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2418 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2419 BOOST_CHECK_EQUAL(queriesCount
, 0);
2422 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
);
2423 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2424 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2425 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2426 BOOST_CHECK_EQUAL(queriesCount
, 0);
2429 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
);
2430 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2431 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2432 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2433 BOOST_CHECK_EQUAL(queriesCount
, 0);
2436 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::A
), QClass::IN
, ret
);
2437 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2438 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2439 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2440 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), "127.0.0.1");
2441 BOOST_CHECK_EQUAL(queriesCount
, 0);
2444 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::AAAA
), QClass::IN
, ret
);
2445 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2446 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2447 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
2448 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(ret
[0])->getCA().toString(), "::1");
2449 BOOST_CHECK_EQUAL(queriesCount
, 0);
2452 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::ANY
), QClass::IN
, ret
);
2453 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2454 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2455 for (const auto& rec
: ret
) {
2456 BOOST_REQUIRE((rec
.d_type
== QType::A
) || rec
.d_type
== QType::AAAA
);
2457 if (rec
.d_type
== QType::A
) {
2458 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(rec
)->getCA().toString(), "127.0.0.1");
2461 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(rec
)->getCA().toString(), "::1");
2464 BOOST_CHECK_EQUAL(queriesCount
, 0);
2467 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2468 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2469 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2470 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2471 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2472 BOOST_CHECK_EQUAL(queriesCount
, 0);
2475 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2476 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2477 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2478 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2479 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2480 BOOST_CHECK_EQUAL(queriesCount
, 0);
2483 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2484 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2485 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2486 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2487 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2488 BOOST_CHECK_EQUAL(queriesCount
, 0);
2491 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2492 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2493 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2494 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2495 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2496 BOOST_CHECK_EQUAL(queriesCount
, 0);
2499 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2500 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2501 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2502 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2503 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2504 BOOST_CHECK_EQUAL(queriesCount
, 0);
2507 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2508 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2509 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2510 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2511 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2512 BOOST_CHECK_EQUAL(queriesCount
, 0);
2515 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz
) {
2516 std::unique_ptr
<SyncRes
> sr
;
2521 const DNSName
target("rpz.powerdns.com.");
2522 const ComboAddress
ns("192.0.2.1:53");
2524 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
) {
2526 if (isRootServer(ip
)) {
2527 setLWResult(res
, false, true, false, true);
2528 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2529 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2531 } else if (ip
== ns
) {
2533 setLWResult(res
, 0, true, false, true);
2534 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2541 DNSFilterEngine::Policy pol
;
2542 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2543 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2544 zone
->setName("Unit test policy 0");
2545 zone
->addNSIPTrigger(Netmask(ns
, 32), pol
);
2546 auto luaconfsCopy
= g_luaconfs
.getCopy();
2547 luaconfsCopy
.dfe
.addZone(zone
);
2548 g_luaconfs
.setState(luaconfsCopy
);
2550 vector
<DNSRecord
> ret
;
2551 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2552 BOOST_CHECK_EQUAL(res
, -2);
2553 BOOST_CHECK_EQUAL(ret
.size(), 0);
2556 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz
) {
2557 std::unique_ptr
<SyncRes
> sr
;
2562 const DNSName
target("rpz.powerdns.com.");
2563 const ComboAddress
ns("[2001:DB8::42]:53");
2565 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
) {
2567 if (isRootServer(ip
)) {
2568 setLWResult(res
, 0, false, false, true);
2569 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2570 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2572 } else if (ip
== ns
) {
2574 setLWResult(res
, 0, true, false, true);
2575 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2582 DNSFilterEngine::Policy pol
;
2583 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2584 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2585 zone
->setName("Unit test policy 0");
2586 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2587 auto luaconfsCopy
= g_luaconfs
.getCopy();
2588 luaconfsCopy
.dfe
.addZone(zone
);
2589 g_luaconfs
.setState(luaconfsCopy
);
2591 vector
<DNSRecord
> ret
;
2592 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2593 BOOST_CHECK_EQUAL(res
, -2);
2594 BOOST_CHECK_EQUAL(ret
.size(), 0);
2597 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz
) {
2598 std::unique_ptr
<SyncRes
> sr
;
2603 const DNSName
target("rpz.powerdns.com.");
2604 const ComboAddress
ns("192.0.2.1:53");
2605 const DNSName
nsName("ns1.powerdns.com.");
2607 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
) {
2609 if (isRootServer(ip
)) {
2610 setLWResult(res
, 0, false, false, true);
2611 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2612 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2614 } else if (ip
== ns
) {
2616 setLWResult(res
, 0, true, false, true);
2617 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2624 DNSFilterEngine::Policy pol
;
2625 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2626 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2627 zone
->setName("Unit test policy 0");
2628 zone
->addNSTrigger(nsName
, pol
);
2629 auto luaconfsCopy
= g_luaconfs
.getCopy();
2630 luaconfsCopy
.dfe
.addZone(zone
);
2631 g_luaconfs
.setState(luaconfsCopy
);
2633 vector
<DNSRecord
> ret
;
2634 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2635 BOOST_CHECK_EQUAL(res
, -2);
2636 BOOST_CHECK_EQUAL(ret
.size(), 0);
2639 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled
) {
2640 std::unique_ptr
<SyncRes
> sr
;
2645 const DNSName
target("rpz.powerdns.com.");
2646 const ComboAddress
ns("192.0.2.1:53");
2647 const DNSName
nsName("ns1.powerdns.com.");
2649 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
) {
2651 if (isRootServer(ip
)) {
2652 setLWResult(res
, 0, false, false, true);
2653 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2654 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2656 } else if (ip
== ns
) {
2658 setLWResult(res
, 0, true, false, true);
2659 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2666 DNSFilterEngine::Policy pol
;
2667 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2668 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2669 zone
->setName("Unit test policy 0");
2670 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2671 zone
->addNSTrigger(nsName
, pol
);
2672 auto luaconfsCopy
= g_luaconfs
.getCopy();
2673 luaconfsCopy
.dfe
.addZone(zone
);
2674 g_luaconfs
.setState(luaconfsCopy
);
2676 /* RPZ is disabled for this query, we should not be blocked */
2677 sr
->setWantsRPZ(false);
2679 vector
<DNSRecord
> ret
;
2680 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2681 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2682 BOOST_CHECK_EQUAL(ret
.size(), 1);
2685 BOOST_AUTO_TEST_CASE(test_forward_zone_nord
) {
2686 std::unique_ptr
<SyncRes
> sr
;
2691 const DNSName
target("powerdns.com.");
2692 const ComboAddress
ns("192.0.2.1:53");
2693 const ComboAddress
forwardedNS("192.0.2.42:53");
2695 SyncRes::AuthDomain ad
;
2696 ad
.d_rdForward
= false;
2697 ad
.d_servers
.push_back(forwardedNS
);
2698 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2700 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
) {
2702 if (ip
== forwardedNS
) {
2703 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2705 setLWResult(res
, 0, true, false, true);
2706 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2713 /* simulate a no-RD query */
2716 vector
<DNSRecord
> ret
;
2717 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2718 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2719 BOOST_CHECK_EQUAL(ret
.size(), 1);
2722 BOOST_AUTO_TEST_CASE(test_forward_zone_rd
) {
2723 std::unique_ptr
<SyncRes
> sr
;
2728 const DNSName
target("powerdns.com.");
2729 const ComboAddress
ns("192.0.2.1:53");
2730 const ComboAddress
forwardedNS("192.0.2.42:53");
2732 SyncRes::AuthDomain ad
;
2733 ad
.d_rdForward
= false;
2734 ad
.d_servers
.push_back(forwardedNS
);
2735 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2737 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
) {
2739 if (ip
== forwardedNS
) {
2740 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2742 setLWResult(res
, 0, true, false, true);
2743 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2750 vector
<DNSRecord
> ret
;
2751 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2752 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2753 BOOST_CHECK_EQUAL(ret
.size(), 1);
2756 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord
) {
2757 std::unique_ptr
<SyncRes
> sr
;
2762 const DNSName
target("powerdns.com.");
2763 const ComboAddress
ns("192.0.2.1:53");
2764 const ComboAddress
forwardedNS("192.0.2.42:53");
2766 SyncRes::AuthDomain ad
;
2767 ad
.d_rdForward
= true;
2768 ad
.d_servers
.push_back(forwardedNS
);
2769 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2771 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
) {
2773 if (ip
== forwardedNS
) {
2774 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2776 setLWResult(res
, 0, true, false, true);
2777 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2784 /* simulate a no-RD query */
2787 vector
<DNSRecord
> ret
;
2788 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2789 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2790 BOOST_CHECK_EQUAL(ret
.size(), 1);
2793 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd
) {
2794 std::unique_ptr
<SyncRes
> sr
;
2799 const DNSName
target("powerdns.com.");
2800 const ComboAddress
ns("192.0.2.1:53");
2801 const ComboAddress
forwardedNS("192.0.2.42:53");
2803 SyncRes::AuthDomain ad
;
2804 ad
.d_rdForward
= true;
2805 ad
.d_servers
.push_back(forwardedNS
);
2806 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2808 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
) {
2810 if (ip
== forwardedNS
) {
2811 BOOST_CHECK_EQUAL(sendRDQuery
, true);
2813 setLWResult(res
, 0, true, false, true);
2814 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2821 vector
<DNSRecord
> ret
;
2822 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2823 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2824 BOOST_CHECK_EQUAL(ret
.size(), 1);
2827 BOOST_AUTO_TEST_CASE(test_auth_zone_oob
) {
2828 std::unique_ptr
<SyncRes
> sr
;
2833 size_t queriesCount
= 0;
2834 const DNSName
target("test.xx.");
2835 const ComboAddress
targetAddr("127.0.0.1");
2836 const DNSName
authZone("test.xx");
2838 SyncRes::AuthDomain ad
;
2841 dr
.d_place
= DNSResourceRecord::ANSWER
;
2843 dr
.d_type
= QType::A
;
2845 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
2846 ad
.d_records
.insert(dr
);
2848 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
2850 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
) {
2855 vector
<DNSRecord
> ret
;
2856 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2857 BOOST_CHECK_EQUAL(res
, 0);
2858 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2859 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2860 BOOST_CHECK_EQUAL(queriesCount
, 0);
2861 BOOST_CHECK(sr
->wasOutOfBand());
2862 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2864 /* a second time, to check that the OOB flag is set when the query cache is used */
2866 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2867 BOOST_CHECK_EQUAL(res
, 0);
2868 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2869 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2870 BOOST_CHECK_EQUAL(queriesCount
, 0);
2871 BOOST_CHECK(sr
->wasOutOfBand());
2872 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2874 /* a third time, to check that the validation is disabled when the OOB flag is set */
2876 sr
->setDNSSECValidationRequested(true);
2877 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2878 BOOST_CHECK_EQUAL(res
, 0);
2879 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2880 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2881 BOOST_CHECK_EQUAL(queriesCount
, 0);
2882 BOOST_CHECK(sr
->wasOutOfBand());
2883 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2886 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_cname
) {
2887 std::unique_ptr
<SyncRes
> sr
;
2892 size_t queriesCount
= 0;
2893 const DNSName
target("cname.test.xx.");
2894 const DNSName
targetCname("cname-target.test.xx.");
2895 const ComboAddress
targetCnameAddr("127.0.0.1");
2896 const DNSName
authZone("test.xx");
2898 SyncRes::AuthDomain ad
;
2901 dr
.d_place
= DNSResourceRecord::ANSWER
;
2903 dr
.d_type
= QType::CNAME
;
2905 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(targetCname
);
2906 ad
.d_records
.insert(dr
);
2908 dr
.d_place
= DNSResourceRecord::ANSWER
;
2909 dr
.d_name
= targetCname
;
2910 dr
.d_type
= QType::A
;
2912 dr
.d_content
= std::make_shared
<ARecordContent
>(targetCnameAddr
);
2913 ad
.d_records
.insert(dr
);
2915 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
2917 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
) {
2922 vector
<DNSRecord
> ret
;
2923 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2924 BOOST_CHECK_EQUAL(res
, 0);
2925 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2926 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2927 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2928 BOOST_CHECK_EQUAL(queriesCount
, 0);
2929 BOOST_CHECK(sr
->wasOutOfBand());
2930 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2932 /* a second time, to check that the OOB flag is set when the query cache is used */
2934 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2935 BOOST_CHECK_EQUAL(res
, 0);
2936 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2937 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2938 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2939 BOOST_CHECK_EQUAL(queriesCount
, 0);
2940 BOOST_CHECK(sr
->wasOutOfBand());
2941 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2943 /* a third time, to check that the validation is disabled when the OOB flag is set */
2945 sr
->setDNSSECValidationRequested(true);
2946 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2947 BOOST_CHECK_EQUAL(res
, 0);
2948 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2949 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2950 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2951 BOOST_CHECK_EQUAL(queriesCount
, 0);
2952 BOOST_CHECK(sr
->wasOutOfBand());
2953 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2956 BOOST_AUTO_TEST_CASE(test_auth_zone
) {
2957 std::unique_ptr
<SyncRes
> sr
;
2962 size_t queriesCount
= 0;
2963 const DNSName
target("powerdns.com.");
2964 const ComboAddress
addr("192.0.2.5");
2966 SyncRes::AuthDomain ad
;
2969 dr
.d_place
= DNSResourceRecord::ANSWER
;
2971 dr
.d_type
= QType::SOA
;
2973 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2974 ad
.d_records
.insert(dr
);
2976 dr
.d_place
= DNSResourceRecord::ANSWER
;
2978 dr
.d_type
= QType::A
;
2980 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
2981 ad
.d_records
.insert(dr
);
2983 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2984 (*map
)[target
] = ad
;
2985 SyncRes::setDomainMap(map
);
2987 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
) {
2990 setLWResult(res
, 0, true, false, true);
2991 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2995 vector
<DNSRecord
> ret
;
2996 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2997 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2998 BOOST_CHECK_EQUAL(ret
.size(), 1);
2999 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3000 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3001 BOOST_CHECK_EQUAL(queriesCount
, 0);
3004 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob
) {
3005 std::unique_ptr
<SyncRes
> sr
;
3010 size_t queriesCount
= 0;
3011 const DNSName
target("powerdns.com.");
3012 const DNSName
authZone("internal.powerdns.com.");
3013 const ComboAddress
addr("192.0.2.5");
3015 SyncRes::AuthDomain ad
;
3016 ad
.d_name
= authZone
;
3018 dr
.d_place
= DNSResourceRecord::ANSWER
;
3019 dr
.d_name
= authZone
;
3020 dr
.d_type
= QType::SOA
;
3022 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3023 ad
.d_records
.insert(dr
);
3025 dr
.d_place
= DNSResourceRecord::ANSWER
;
3026 dr
.d_name
= authZone
;
3027 dr
.d_type
= QType::A
;
3029 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3030 ad
.d_records
.insert(dr
);
3032 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3033 (*map
)[authZone
] = ad
;
3034 SyncRes::setDomainMap(map
);
3036 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
) {
3040 if (domain
== target
) {
3041 setLWResult(res
, 0, true, false, true);
3042 addRecordToLW(res
, target
, QType::CNAME
, authZone
.toString(), DNSResourceRecord::ANSWER
, 3600);
3049 vector
<DNSRecord
> ret
;
3050 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3051 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3052 BOOST_CHECK_EQUAL(ret
.size(), 2);
3053 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3054 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), authZone
.toString());
3055 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3056 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
3057 BOOST_CHECK_EQUAL(queriesCount
, 1);
3060 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb
) {
3061 std::unique_ptr
<SyncRes
> sr
;
3066 size_t queriesCount
= 0;
3067 const DNSName
target("powerdns.com.");
3068 const DNSName
externalCNAME("www.open-xchange.com.");
3069 const ComboAddress
addr("192.0.2.5");
3071 SyncRes::AuthDomain ad
;
3074 dr
.d_place
= DNSResourceRecord::ANSWER
;
3076 dr
.d_type
= QType::SOA
;
3078 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3079 ad
.d_records
.insert(dr
);
3081 dr
.d_place
= DNSResourceRecord::ANSWER
;
3083 dr
.d_type
= QType::CNAME
;
3085 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(externalCNAME
);
3086 ad
.d_records
.insert(dr
);
3088 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3089 (*map
)[target
] = ad
;
3090 SyncRes::setDomainMap(map
);
3092 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
) {
3096 if (domain
== externalCNAME
) {
3097 setLWResult(res
, 0, true, false, true);
3098 addRecordToLW(res
, externalCNAME
, QType::A
, addr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3105 vector
<DNSRecord
> ret
;
3106 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3107 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3108 BOOST_CHECK_EQUAL(ret
.size(), 2);
3109 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3110 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), externalCNAME
.toString());
3111 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3112 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
3113 BOOST_CHECK_EQUAL(queriesCount
, 1);
3116 BOOST_AUTO_TEST_CASE(test_auth_zone_nodata
) {
3117 std::unique_ptr
<SyncRes
> sr
;
3122 size_t queriesCount
= 0;
3123 const DNSName
target("nodata.powerdns.com.");
3124 const DNSName
authZone("powerdns.com");
3126 SyncRes::AuthDomain ad
;
3127 ad
.d_name
= authZone
;
3129 dr
.d_place
= DNSResourceRecord::ANSWER
;
3131 dr
.d_type
= QType::A
;
3133 dr
.d_content
= std::make_shared
<ARecordContent
>(ComboAddress("192.0.2.1"));
3134 ad
.d_records
.insert(dr
);
3136 dr
.d_place
= DNSResourceRecord::ANSWER
;
3137 dr
.d_name
= authZone
;
3138 dr
.d_type
= QType::SOA
;
3140 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3141 ad
.d_records
.insert(dr
);
3143 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3144 (*map
)[authZone
] = ad
;
3145 SyncRes::setDomainMap(map
);
3147 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
) {
3154 vector
<DNSRecord
> ret
;
3155 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3156 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3157 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3158 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3159 BOOST_CHECK_EQUAL(queriesCount
, 0);
3162 BOOST_AUTO_TEST_CASE(test_auth_zone_nx
) {
3163 std::unique_ptr
<SyncRes
> sr
;
3168 size_t queriesCount
= 0;
3169 const DNSName
target("nx.powerdns.com.");
3170 const DNSName
authZone("powerdns.com");
3172 SyncRes::AuthDomain ad
;
3173 ad
.d_name
= authZone
;
3175 dr
.d_place
= DNSResourceRecord::ANSWER
;
3176 dr
.d_name
= DNSName("powerdns.com.");
3177 dr
.d_type
= QType::SOA
;
3179 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3180 ad
.d_records
.insert(dr
);
3182 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3183 (*map
)[authZone
] = ad
;
3184 SyncRes::setDomainMap(map
);
3186 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
) {
3193 vector
<DNSRecord
> ret
;
3194 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3195 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
3196 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3197 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3198 BOOST_CHECK_EQUAL(queriesCount
, 0);
3201 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation
) {
3202 std::unique_ptr
<SyncRes
> sr
;
3203 initSR(sr
, true, false);
3207 size_t queriesCount
= 0;
3208 const DNSName
target("www.test.powerdns.com.");
3209 const ComboAddress
targetAddr("192.0.2.2");
3210 const DNSName
ns("ns1.test.powerdns.com.");
3211 const ComboAddress
nsAddr("192.0.2.1");
3212 const DNSName
authZone("powerdns.com");
3214 SyncRes::AuthDomain ad
;
3215 ad
.d_name
= authZone
;
3217 dr
.d_place
= DNSResourceRecord::ANSWER
;
3218 dr
.d_name
= authZone
;
3219 dr
.d_type
= QType::SOA
;
3221 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3222 ad
.d_records
.insert(dr
);
3224 dr
.d_place
= DNSResourceRecord::ANSWER
;
3225 dr
.d_name
= DNSName("test.powerdns.com.");
3226 dr
.d_type
= QType::NS
;
3228 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3229 ad
.d_records
.insert(dr
);
3231 dr
.d_place
= DNSResourceRecord::ANSWER
;
3233 dr
.d_type
= QType::A
;
3235 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3236 ad
.d_records
.insert(dr
);
3238 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3239 (*map
)[authZone
] = ad
;
3240 SyncRes::setDomainMap(map
);
3243 auto luaconfsCopy
= g_luaconfs
.getCopy();
3244 luaconfsCopy
.dsAnchors
.clear();
3245 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
3246 g_luaconfs
.setState(luaconfsCopy
);
3248 sr
->setAsyncCallback([&queriesCount
,target
,targetAddr
,nsAddr
,authZone
,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
) {
3251 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
3252 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
, domain
== authZone
);
3255 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3256 setLWResult(res
, 0, true, false, true);
3257 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3264 sr
->setDNSSECValidationRequested(true);
3265 vector
<DNSRecord
> ret
;
3266 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3267 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3268 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3269 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3270 BOOST_CHECK_EQUAL(queriesCount
, 4);
3271 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
3274 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point
) {
3275 std::unique_ptr
<SyncRes
> sr
;
3280 size_t queriesCount
= 0;
3281 const DNSName
target("test.powerdns.com.");
3282 const ComboAddress
targetAddr("192.0.2.2");
3283 const DNSName
ns("ns1.test.powerdns.com.");
3284 const ComboAddress
nsAddr("192.0.2.1");
3285 const DNSName
authZone("powerdns.com");
3287 SyncRes::AuthDomain ad
;
3288 ad
.d_name
= authZone
;
3290 dr
.d_place
= DNSResourceRecord::ANSWER
;
3291 dr
.d_name
= authZone
;
3292 dr
.d_type
= QType::SOA
;
3294 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3295 ad
.d_records
.insert(dr
);
3297 dr
.d_place
= DNSResourceRecord::ANSWER
;
3298 dr
.d_name
= DNSName("test.powerdns.com.");
3299 dr
.d_type
= QType::NS
;
3301 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3302 ad
.d_records
.insert(dr
);
3304 dr
.d_place
= DNSResourceRecord::ANSWER
;
3306 dr
.d_type
= QType::A
;
3308 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3309 ad
.d_records
.insert(dr
);
3311 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3312 (*map
)[authZone
] = ad
;
3313 SyncRes::setDomainMap(map
);
3315 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
) {
3319 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3320 setLWResult(res
, 0, true, false, true);
3321 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3328 vector
<DNSRecord
> ret
;
3329 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3330 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3331 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3332 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3333 BOOST_CHECK_EQUAL(queriesCount
, 1);
3336 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard
) {
3337 std::unique_ptr
<SyncRes
> sr
;
3342 size_t queriesCount
= 0;
3343 const DNSName
target("test.powerdns.com.");
3344 const ComboAddress
targetAddr("192.0.2.2");
3345 const DNSName
authZone("powerdns.com");
3347 SyncRes::AuthDomain ad
;
3348 ad
.d_name
= authZone
;
3350 dr
.d_place
= DNSResourceRecord::ANSWER
;
3351 dr
.d_name
= authZone
;
3352 dr
.d_type
= QType::SOA
;
3354 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3355 ad
.d_records
.insert(dr
);
3357 dr
.d_place
= DNSResourceRecord::ANSWER
;
3358 dr
.d_name
= DNSName("*.powerdns.com.");
3359 dr
.d_type
= QType::A
;
3361 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3362 ad
.d_records
.insert(dr
);
3364 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3365 (*map
)[authZone
] = ad
;
3366 SyncRes::setDomainMap(map
);
3368 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
) {
3375 vector
<DNSRecord
> ret
;
3376 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3377 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3378 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3379 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3380 BOOST_CHECK_EQUAL(queriesCount
, 0);
3383 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata
) {
3384 std::unique_ptr
<SyncRes
> sr
;
3389 size_t queriesCount
= 0;
3390 const DNSName
target("test.powerdns.com.");
3391 const ComboAddress
targetAddr("192.0.2.2");
3392 const DNSName
authZone("powerdns.com");
3394 SyncRes::AuthDomain ad
;
3395 ad
.d_name
= authZone
;
3397 dr
.d_place
= DNSResourceRecord::ANSWER
;
3398 dr
.d_name
= authZone
;
3399 dr
.d_type
= QType::SOA
;
3401 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3402 ad
.d_records
.insert(dr
);
3404 dr
.d_place
= DNSResourceRecord::ANSWER
;
3405 dr
.d_name
= DNSName("*.powerdns.com.");
3406 dr
.d_type
= QType::A
;
3408 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3409 ad
.d_records
.insert(dr
);
3411 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3412 (*map
)[authZone
] = ad
;
3413 SyncRes::setDomainMap(map
);
3415 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
) {
3422 vector
<DNSRecord
> ret
;
3423 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3424 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3425 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3426 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3427 BOOST_CHECK_EQUAL(queriesCount
, 0);
3430 BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only
) {
3431 std::unique_ptr
<SyncRes
> sr
;
3436 size_t queriesCount
= 0;
3437 const DNSName
target("powerdns.com.");
3438 const ComboAddress
addr("192.0.2.5");
3440 SyncRes::AuthDomain ad
;
3443 dr
.d_place
= DNSResourceRecord::ANSWER
;
3445 dr
.d_type
= QType::SOA
;
3447 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3448 ad
.d_records
.insert(dr
);
3450 dr
.d_place
= DNSResourceRecord::ANSWER
;
3452 dr
.d_type
= QType::A
;
3454 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3455 ad
.d_records
.insert(dr
);
3457 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3458 (*map
)[target
] = ad
;
3459 SyncRes::setDomainMap(map
);
3461 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
) {
3464 setLWResult(res
, 0, true, false, true);
3465 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
3469 /* simulate a no-RD query */
3472 vector
<DNSRecord
> ret
;
3473 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3474 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3475 BOOST_CHECK_EQUAL(ret
.size(), 1);
3476 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3477 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3478 BOOST_CHECK_EQUAL(queriesCount
, 0);
3481 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig
) {
3484 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3485 dcke
->create(dcke
->getBits());
3486 // cerr<<dcke->convertToISC()<<endl;
3487 DNSSECPrivateKey dpk
;
3491 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
3492 recordcontents
.push_back(getRecordContent(QType::A
, "192.0.2.1"));
3494 DNSName
qname("powerdns.com.");
3496 time_t now
= time(nullptr);
3497 RRSIGRecordContent rrc
;
3498 /* this RRSIG is valid for the current second only */
3499 computeRRSIG(dpk
, qname
, qname
, QType::A
, 600, 0, rrc
, recordcontents
, boost::none
, now
);
3502 keyset
.insert(std::make_shared
<DNSKEYRecordContent
>(dpk
.getDNSKEY()));
3504 std::vector
<std::shared_ptr
<RRSIGRecordContent
> > sigs
;
3505 sigs
.push_back(std::make_shared
<RRSIGRecordContent
>(rrc
));
3507 BOOST_CHECK(validateWithKeySet(now
, qname
, recordcontents
, sigs
, keyset
));
3510 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk
) {
3511 std::unique_ptr
<SyncRes
> sr
;
3514 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3517 const DNSName
target(".");
3520 auto luaconfsCopy
= g_luaconfs
.getCopy();
3521 luaconfsCopy
.dsAnchors
.clear();
3522 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3523 g_luaconfs
.setState(luaconfsCopy
);
3525 size_t queriesCount
= 0;
3527 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
) {
3530 if (domain
== target
&& type
== QType::NS
) {
3532 setLWResult(res
, 0, true, false, true);
3533 char addr
[] = "a.root-servers.net.";
3534 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3536 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3539 addRRSIG(keys
, res
->d_records
, domain
, 300);
3541 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3542 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3545 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3547 setLWResult(res
, 0, true, false, true);
3549 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3550 addRRSIG(keys
, res
->d_records
, domain
, 300);
3558 vector
<DNSRecord
> ret
;
3559 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3560 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3561 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3562 /* 13 NS + 1 RRSIG */
3563 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3564 BOOST_CHECK_EQUAL(queriesCount
, 2);
3566 /* again, to test the cache */
3568 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3569 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3570 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3571 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3572 BOOST_CHECK_EQUAL(queriesCount
, 2);
3575 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk
) {
3576 std::unique_ptr
<SyncRes
> sr
;
3579 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3582 const DNSName
target(".");
3583 testkeysset_t zskeys
;
3584 testkeysset_t kskeys
;
3586 /* Generate key material for "." */
3587 auto dckeZ
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3588 dckeZ
->create(dckeZ
->getBits());
3589 DNSSECPrivateKey ksk
;
3592 DSRecordContent kskds
= makeDSFromDNSKey(target
, ksk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3594 auto dckeK
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3595 dckeK
->create(dckeK
->getBits());
3596 DNSSECPrivateKey zsk
;
3599 DSRecordContent zskds
= makeDSFromDNSKey(target
, zsk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3601 kskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(ksk
, kskds
);
3602 zskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(zsk
, zskds
);
3604 /* Set the root DS */
3605 auto luaconfsCopy
= g_luaconfs
.getCopy();
3606 luaconfsCopy
.dsAnchors
.clear();
3607 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(kskds
);
3608 g_luaconfs
.setState(luaconfsCopy
);
3610 size_t queriesCount
= 0;
3612 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
) {
3615 if (domain
== target
&& type
== QType::NS
) {
3617 setLWResult(res
, 0, true, false, true);
3618 char addr
[] = "a.root-servers.net.";
3619 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3621 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3624 addRRSIG(zskeys
, res
->d_records
, domain
, 300);
3626 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3627 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3630 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3632 setLWResult(res
, 0, true, false, true);
3634 addDNSKEY(kskeys
, domain
, 300, res
->d_records
);
3635 addDNSKEY(zskeys
, domain
, 300, res
->d_records
);
3636 addRRSIG(kskeys
, res
->d_records
, domain
, 300);
3644 vector
<DNSRecord
> ret
;
3645 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3646 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3647 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3648 /* 13 NS + 1 RRSIG */
3649 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3650 BOOST_CHECK_EQUAL(queriesCount
, 2);
3652 /* again, to test the cache */
3654 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3655 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3656 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3657 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3658 BOOST_CHECK_EQUAL(queriesCount
, 2);
3661 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey
) {
3662 std::unique_ptr
<SyncRes
> sr
;
3665 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3668 const DNSName
target(".");
3671 auto luaconfsCopy
= g_luaconfs
.getCopy();
3672 luaconfsCopy
.dsAnchors
.clear();
3673 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3674 g_luaconfs
.setState(luaconfsCopy
);
3676 size_t queriesCount
= 0;
3678 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
) {
3681 if (domain
== target
&& type
== QType::NS
) {
3683 setLWResult(res
, 0, true, false, true);
3684 char addr
[] = "a.root-servers.net.";
3685 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3687 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3690 addRRSIG(keys
, res
->d_records
, domain
, 300);
3692 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3693 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3696 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3698 setLWResult(res
, 0, true, false, true);
3708 vector
<DNSRecord
> ret
;
3709 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3710 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3711 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3712 /* 13 NS + 1 RRSIG */
3713 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3714 BOOST_CHECK_EQUAL(queriesCount
, 2);
3716 /* again, to test the cache */
3718 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3719 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3720 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3721 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3722 BOOST_CHECK_EQUAL(queriesCount
, 2);
3725 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds
) {
3726 std::unique_ptr
<SyncRes
> sr
;
3729 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3732 const DNSName
target(".");
3733 testkeysset_t dskeys
;
3736 /* Generate key material for "." */
3737 auto dckeDS
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3738 dckeDS
->create(dckeDS
->getBits());
3739 DNSSECPrivateKey dskey
;
3740 dskey
.d_flags
= 257;
3741 dskey
.setKey(dckeDS
);
3742 DSRecordContent drc
= makeDSFromDNSKey(target
, dskey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3744 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3745 dcke
->create(dcke
->getBits());
3746 DNSSECPrivateKey dpk
;
3749 DSRecordContent uselessdrc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3751 dskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dskey
, drc
);
3752 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, uselessdrc
);
3754 /* Set the root DS */
3755 auto luaconfsCopy
= g_luaconfs
.getCopy();
3756 luaconfsCopy
.dsAnchors
.clear();
3757 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3758 g_luaconfs
.setState(luaconfsCopy
);
3760 size_t queriesCount
= 0;
3762 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
) {
3765 if (domain
== target
&& type
== QType::NS
) {
3767 setLWResult(res
, 0, true, false, true);
3768 char addr
[] = "a.root-servers.net.";
3769 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3771 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3774 addRRSIG(keys
, res
->d_records
, domain
, 300);
3776 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3777 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3780 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3782 setLWResult(res
, 0, true, false, true);
3784 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3785 addRRSIG(keys
, res
->d_records
, domain
, 300);
3793 vector
<DNSRecord
> ret
;
3794 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3795 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3796 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3797 /* 13 NS + 1 RRSIG */
3798 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3799 BOOST_CHECK_EQUAL(queriesCount
, 2);
3801 /* again, to test the cache */
3803 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3804 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3805 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3806 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3807 BOOST_CHECK_EQUAL(queriesCount
, 2);
3810 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey
) {
3811 std::unique_ptr
<SyncRes
> sr
;
3814 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3817 const DNSName
target(".");
3819 testkeysset_t rrsigkeys
;
3821 auto luaconfsCopy
= g_luaconfs
.getCopy();
3822 luaconfsCopy
.dsAnchors
.clear();
3823 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3824 g_luaconfs
.setState(luaconfsCopy
);
3826 auto dckeRRSIG
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3827 dckeRRSIG
->create(dckeRRSIG
->getBits());
3828 DNSSECPrivateKey rrsigkey
;
3829 rrsigkey
.d_flags
= 257;
3830 rrsigkey
.setKey(dckeRRSIG
);
3831 DSRecordContent rrsigds
= makeDSFromDNSKey(target
, rrsigkey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3833 rrsigkeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(rrsigkey
, rrsigds
);
3835 size_t queriesCount
= 0;
3837 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
) {
3840 if (domain
== target
&& type
== QType::NS
) {
3842 setLWResult(res
, 0, true, false, true);
3843 char addr
[] = "a.root-servers.net.";
3844 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3846 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3849 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3851 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3852 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3855 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3857 setLWResult(res
, 0, true, false, true);
3859 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3860 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3868 vector
<DNSRecord
> ret
;
3869 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3870 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3871 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3872 /* 13 NS + 1 RRSIG */
3873 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3874 BOOST_CHECK_EQUAL(queriesCount
, 2);
3876 /* again, to test the cache */
3878 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3879 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3880 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3881 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3882 BOOST_CHECK_EQUAL(queriesCount
, 2);
3885 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig
) {
3886 std::unique_ptr
<SyncRes
> sr
;
3889 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3892 const DNSName
target(".");
3895 auto luaconfsCopy
= g_luaconfs
.getCopy();
3896 luaconfsCopy
.dsAnchors
.clear();
3897 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3898 g_luaconfs
.setState(luaconfsCopy
);
3900 size_t queriesCount
= 0;
3902 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
) {
3905 if (domain
== target
&& type
== QType::NS
) {
3907 setLWResult(res
, 0, true, false, true);
3908 char addr
[] = "a.root-servers.net.";
3909 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3911 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3916 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3917 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3920 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3922 setLWResult(res
, 0, true, false, true);
3924 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3925 addRRSIG(keys
, res
->d_records
, domain
, 300);
3933 vector
<DNSRecord
> ret
;
3934 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3935 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3936 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3937 /* 13 NS + 0 RRSIG */
3938 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3939 /* no RRSIG so no query for DNSKEYs */
3940 BOOST_CHECK_EQUAL(queriesCount
, 1);
3942 /* again, to test the cache */
3944 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3945 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3946 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3947 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3948 BOOST_CHECK_EQUAL(queriesCount
, 1);
3951 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm
) {
3952 std::unique_ptr
<SyncRes
> sr
;
3955 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3958 const DNSName
target(".");
3961 /* Generate key material for "." */
3962 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3963 dcke
->create(dcke
->getBits());
3964 DNSSECPrivateKey dpk
;
3967 /* Fake algorithm number (private) */
3968 dpk
.d_algorithm
= 253;
3970 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3971 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, drc
);
3972 /* Fake algorithm number (private) */
3973 drc
.d_algorithm
= 253;
3975 /* Set the root DS */
3976 auto luaconfsCopy
= g_luaconfs
.getCopy();
3977 luaconfsCopy
.dsAnchors
.clear();
3978 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3979 g_luaconfs
.setState(luaconfsCopy
);
3981 size_t queriesCount
= 0;
3983 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
) {
3986 if (domain
== target
&& type
== QType::NS
) {
3988 setLWResult(res
, 0, true, false, true);
3989 char addr
[] = "a.root-servers.net.";
3990 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3992 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3995 addRRSIG(keys
, res
->d_records
, domain
, 300);
3997 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3998 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4001 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4003 setLWResult(res
, 0, true, false, true);
4005 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4006 addRRSIG(keys
, res
->d_records
, domain
, 300);
4014 vector
<DNSRecord
> ret
;
4015 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4016 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4017 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4018 /* 13 NS + 1 RRSIG */
4019 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4020 /* no supported DS so no query for DNSKEYs */
4021 BOOST_CHECK_EQUAL(queriesCount
, 1);
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(), Insecure
);
4028 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4029 BOOST_CHECK_EQUAL(queriesCount
, 1);
4032 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest
) {
4033 std::unique_ptr
<SyncRes
> sr
;
4036 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4039 const DNSName
target(".");
4042 /* Generate key material for "." */
4043 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
4044 dcke
->create(dcke
->getBits());
4045 DNSSECPrivateKey dpk
;
4048 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
4049 /* Fake digest number (reserved) */
4050 drc
.d_digesttype
= 0;
4052 keys
[target
] = std::pair
<DNSSECPrivateKey
, DSRecordContent
>(dpk
, drc
);
4054 /* Set the root DS */
4055 auto luaconfsCopy
= g_luaconfs
.getCopy();
4056 luaconfsCopy
.dsAnchors
.clear();
4057 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
4058 g_luaconfs
.setState(luaconfsCopy
);
4060 size_t queriesCount
= 0;
4062 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
) {
4065 if (domain
== target
&& type
== QType::NS
) {
4067 setLWResult(res
, 0, true, false, true);
4068 char addr
[] = "a.root-servers.net.";
4069 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4071 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4074 addRRSIG(keys
, res
->d_records
, domain
, 300);
4076 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4077 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4080 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4082 setLWResult(res
, 0, true, false, true);
4084 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4085 addRRSIG(keys
, res
->d_records
, domain
, 300);
4093 vector
<DNSRecord
> ret
;
4094 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4095 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4096 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4097 /* 13 NS + 1 RRSIG */
4098 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4099 /* no supported DS so no query for DNSKEYs */
4100 BOOST_CHECK_EQUAL(queriesCount
, 1);
4102 /* again, to test the cache */
4104 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4105 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4106 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4107 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4108 BOOST_CHECK_EQUAL(queriesCount
, 1);
4111 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig
) {
4112 std::unique_ptr
<SyncRes
> sr
;
4115 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4118 const DNSName
target(".");
4121 auto luaconfsCopy
= g_luaconfs
.getCopy();
4122 luaconfsCopy
.dsAnchors
.clear();
4123 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4125 g_luaconfs
.setState(luaconfsCopy
);
4127 size_t queriesCount
= 0;
4129 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
) {
4132 if (domain
== target
&& type
== QType::NS
) {
4134 setLWResult(res
, 0, true, false, true);
4135 char addr
[] = "a.root-servers.net.";
4136 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4138 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4141 addRRSIG(keys
, res
->d_records
, domain
, 300, true);
4143 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4144 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4147 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4149 setLWResult(res
, 0, true, false, true);
4151 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4152 addRRSIG(keys
, res
->d_records
, domain
, 300);
4160 vector
<DNSRecord
> ret
;
4161 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4162 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4163 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4164 /* 13 NS + 1 RRSIG */
4165 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4166 BOOST_CHECK_EQUAL(queriesCount
, 2);
4168 /* again, to test the cache */
4170 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4171 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4172 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4173 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4174 BOOST_CHECK_EQUAL(queriesCount
, 2);
4177 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo
) {
4178 std::unique_ptr
<SyncRes
> sr
;
4181 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4184 const DNSName
target(".");
4187 auto luaconfsCopy
= g_luaconfs
.getCopy();
4188 luaconfsCopy
.dsAnchors
.clear();
4189 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4191 g_luaconfs
.setState(luaconfsCopy
);
4193 size_t queriesCount
= 0;
4195 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
) {
4198 if (domain
== target
&& type
== QType::NS
) {
4200 setLWResult(res
, 0, true, false, true);
4201 char addr
[] = "a.root-servers.net.";
4202 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4204 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4207 /* FORCE WRONG ALGO */
4208 addRRSIG(keys
, res
->d_records
, domain
, 300, false, DNSSECKeeper::RSASHA256
);
4210 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4211 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4214 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4216 setLWResult(res
, 0, true, false, true);
4218 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4219 addRRSIG(keys
, res
->d_records
, domain
, 300);
4227 vector
<DNSRecord
> ret
;
4228 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4229 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4230 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4231 /* 13 NS + 1 RRSIG */
4232 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4233 BOOST_CHECK_EQUAL(queriesCount
, 2);
4235 /* again, to test the cache */
4237 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4238 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4239 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4240 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4241 BOOST_CHECK_EQUAL(queriesCount
, 2);
4244 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos
) {
4245 std::unique_ptr
<SyncRes
> sr
;
4248 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4251 const DNSName
target("powerdns.com.");
4252 const ComboAddress
targetAddr("192.0.2.42");
4255 auto luaconfsCopy
= g_luaconfs
.getCopy();
4256 luaconfsCopy
.dsAnchors
.clear();
4257 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4258 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4259 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384
, DNSSECKeeper::SHA384
, keys
);
4261 g_luaconfs
.setState(luaconfsCopy
);
4263 size_t queriesCount
= 0;
4265 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
) {
4268 DNSName auth
= domain
;
4269 if (domain
== target
) {
4270 auth
= DNSName("powerdns.com.");
4273 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4274 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4277 if (isRootServer(ip
)) {
4278 setLWResult(res
, 0, false, false, true);
4279 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4280 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4281 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4282 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4286 if (ip
== ComboAddress("192.0.2.1:53")) {
4287 if (domain
== DNSName("com.")) {
4288 setLWResult(res
, 0, true, false, true);
4289 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4290 addRRSIG(keys
, res
->d_records
, domain
, 300);
4291 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4292 addRRSIG(keys
, res
->d_records
, domain
, 300);
4295 setLWResult(res
, 0, false, false, true);
4296 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4297 addDS(auth
, 300, res
->d_records
, keys
);
4298 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4299 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4304 if (ip
== ComboAddress("192.0.2.2:53")) {
4305 if (type
== QType::NS
) {
4306 setLWResult(res
, 0, true, false, true);
4307 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4308 addRRSIG(keys
, res
->d_records
, auth
, 300);
4309 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4310 addRRSIG(keys
, res
->d_records
, auth
, 300);
4313 setLWResult(res
, RCode::NoError
, true, false, true);
4314 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4315 addRRSIG(keys
, res
->d_records
, auth
, 300);
4323 vector
<DNSRecord
> ret
;
4324 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4325 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4326 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4327 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4328 BOOST_CHECK_EQUAL(queriesCount
, 8);
4330 /* again, to test the cache */
4332 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4333 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4334 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4335 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4336 BOOST_CHECK_EQUAL(queriesCount
, 8);
4339 BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns
) {
4340 std::unique_ptr
<SyncRes
> sr
;
4343 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4346 const DNSName
target("powerdns.com.");
4347 const ComboAddress
targetAddr("192.0.2.42");
4350 auto luaconfsCopy
= g_luaconfs
.getCopy();
4351 luaconfsCopy
.dsAnchors
.clear();
4352 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4353 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4354 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4355 g_luaconfs
.setState(luaconfsCopy
);
4357 size_t queriesCount
= 0;
4359 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
) {
4362 DNSName auth
= domain
;
4363 if (domain
== target
) {
4364 auth
= DNSName("powerdns.com.");
4367 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4368 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4371 if (isRootServer(ip
)) {
4372 setLWResult(res
, 0, false, false, true);
4373 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4374 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4375 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4376 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4380 if (ip
== ComboAddress("192.0.2.1:53")) {
4381 if (domain
== DNSName("com.")) {
4382 setLWResult(res
, 0, true, false, true);
4383 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4384 addRRSIG(keys
, res
->d_records
, domain
, 300);
4385 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4386 addRRSIG(keys
, res
->d_records
, domain
, 300);
4389 setLWResult(res
, 0, false, false, true);
4390 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4391 addDS(auth
, 300, res
->d_records
, keys
);
4392 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4393 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4398 if (ip
== ComboAddress("192.0.2.2:53")) {
4399 if (type
== QType::NS
) {
4400 setLWResult(res
, 0, true, false, true);
4401 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4402 addRRSIG(keys
, res
->d_records
, auth
, 300);
4403 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4404 addRRSIG(keys
, res
->d_records
, auth
, 300);
4407 setLWResult(res
, RCode::NoError
, true, false, true);
4408 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4409 addRRSIG(keys
, res
->d_records
, auth
, 300);
4417 vector
<DNSRecord
> ret
;
4418 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4419 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4420 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4421 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4422 BOOST_CHECK_EQUAL(queriesCount
, 8);
4424 /* again, to test the cache */
4426 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4427 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4428 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4429 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4430 BOOST_CHECK_EQUAL(queriesCount
, 8);
4432 /* this time we ask for the NS that should be in the cache, to check
4433 the validation status */
4435 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4436 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4437 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4438 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4439 BOOST_CHECK_EQUAL(queriesCount
, 9);
4443 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns
) {
4444 std::unique_ptr
<SyncRes
> sr
;
4447 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4450 const DNSName
target("powerdns.com.");
4451 const ComboAddress
targetAddr("192.0.2.42");
4454 auto luaconfsCopy
= g_luaconfs
.getCopy();
4455 luaconfsCopy
.dsAnchors
.clear();
4456 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4457 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4458 g_luaconfs
.setState(luaconfsCopy
);
4460 size_t queriesCount
= 0;
4462 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
) {
4465 DNSName auth
= domain
;
4466 if (domain
== target
) {
4467 auth
= DNSName("powerdns.com.");
4470 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4471 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4474 if (isRootServer(ip
)) {
4475 setLWResult(res
, 0, false, false, true);
4476 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4477 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4478 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4479 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4483 if (ip
== ComboAddress("192.0.2.1:53")) {
4484 if (domain
== DNSName("com.")) {
4485 setLWResult(res
, 0, true, false, true);
4486 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4487 addRRSIG(keys
, res
->d_records
, domain
, 300);
4488 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4489 addRRSIG(keys
, res
->d_records
, domain
, 300);
4492 setLWResult(res
, 0, false, false, true);
4493 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4495 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
4496 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4497 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4502 if (ip
== ComboAddress("192.0.2.2:53")) {
4503 if (type
== QType::NS
) {
4504 setLWResult(res
, 0, true, false, true);
4505 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4506 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4509 setLWResult(res
, RCode::NoError
, true, false, true);
4510 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4518 vector
<DNSRecord
> ret
;
4519 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4520 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4521 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4522 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4523 BOOST_CHECK_EQUAL(queriesCount
, 7);
4525 /* again, to test the cache */
4527 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4528 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4529 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4530 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4531 BOOST_CHECK_EQUAL(queriesCount
, 7);
4533 /* this time we ask for the NS that should be in the cache, to check
4534 the validation status */
4536 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4537 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4538 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4539 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4540 BOOST_CHECK_EQUAL(queriesCount
, 8);
4543 BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta
) {
4544 std::unique_ptr
<SyncRes
> sr
;
4547 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4550 const DNSName
target("powerdns.com.");
4551 const ComboAddress
targetAddr("192.0.2.42");
4554 auto luaconfsCopy
= g_luaconfs
.getCopy();
4555 luaconfsCopy
.dsAnchors
.clear();
4556 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4557 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4558 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4560 /* Add a NTA for "powerdns.com" */
4561 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4563 g_luaconfs
.setState(luaconfsCopy
);
4565 size_t queriesCount
= 0;
4567 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
) {
4570 DNSName auth
= domain
;
4571 if (domain
== target
) {
4572 auth
= DNSName("powerdns.com.");
4575 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4576 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4579 if (isRootServer(ip
)) {
4580 setLWResult(res
, 0, false, false, true);
4581 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4582 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4583 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4584 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4588 if (ip
== ComboAddress("192.0.2.1:53")) {
4589 if (domain
== DNSName("com.")) {
4590 setLWResult(res
, 0, true, false, true);
4591 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4592 addRRSIG(keys
, res
->d_records
, domain
, 300);
4593 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4594 addRRSIG(keys
, res
->d_records
, domain
, 300);
4597 setLWResult(res
, 0, false, false, true);
4598 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4599 addDS(auth
, 300, res
->d_records
, keys
);
4600 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4601 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4606 if (ip
== ComboAddress("192.0.2.2:53")) {
4607 if (type
== QType::NS
) {
4608 setLWResult(res
, 0, true, false, true);
4609 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4610 addRRSIG(keys
, res
->d_records
, auth
, 300);
4611 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4612 addRRSIG(keys
, res
->d_records
, auth
, 300);
4615 setLWResult(res
, RCode::NoError
, true, false, true);
4616 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4617 addRRSIG(keys
, res
->d_records
, auth
, 300);
4625 vector
<DNSRecord
> ret
;
4626 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4627 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4628 /* Should be insecure because of the NTA */
4629 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4630 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4631 BOOST_CHECK_EQUAL(queriesCount
, 5);
4633 /* again, to test the cache */
4635 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4636 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4637 /* Should be insecure because of the NTA */
4638 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4639 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4640 BOOST_CHECK_EQUAL(queriesCount
, 5);
4643 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta
) {
4644 std::unique_ptr
<SyncRes
> sr
;
4647 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4650 const DNSName
target("powerdns.com.");
4651 const ComboAddress
targetAddr("192.0.2.42");
4654 auto luaconfsCopy
= g_luaconfs
.getCopy();
4655 luaconfsCopy
.dsAnchors
.clear();
4656 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4657 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4658 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4660 /* Add a NTA for "powerdns.com" */
4661 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4663 g_luaconfs
.setState(luaconfsCopy
);
4665 size_t queriesCount
= 0;
4667 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
) {
4670 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4671 setLWResult(res
, 0, false, false, true);
4672 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4676 if (isRootServer(ip
)) {
4677 setLWResult(res
, 0, false, false, true);
4678 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4679 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4682 else if (ip
== ComboAddress("192.0.2.1:53")) {
4683 if (domain
== DNSName("com.")) {
4684 setLWResult(res
, 0, true, false, true);
4685 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4686 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4689 setLWResult(res
, 0, false, false, true);
4690 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4691 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4695 else if (ip
== ComboAddress("192.0.2.2:53")) {
4696 if (type
== QType::NS
) {
4697 setLWResult(res
, 0, true, false, true);
4698 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4699 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4702 setLWResult(res
, RCode::NoError
, true, false, true);
4703 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4712 /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
4713 vector
<DNSRecord
> ret
;
4714 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4715 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4716 /* Should be insecure because of the NTA */
4717 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4718 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4719 BOOST_CHECK_EQUAL(queriesCount
, 4);
4721 /* again, to test the cache */
4723 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4724 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4725 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4726 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4727 BOOST_CHECK_EQUAL(queriesCount
, 4);
4730 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec
) {
4731 std::unique_ptr
<SyncRes
> sr
;
4734 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4737 const DNSName
target("powerdns.com.");
4740 auto luaconfsCopy
= g_luaconfs
.getCopy();
4741 luaconfsCopy
.dsAnchors
.clear();
4742 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4743 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4744 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4746 g_luaconfs
.setState(luaconfsCopy
);
4748 size_t queriesCount
= 0;
4750 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
) {
4753 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4754 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
4757 if (isRootServer(ip
)) {
4758 setLWResult(res
, 0, false, false, true);
4759 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4760 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4761 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4762 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4765 else if (ip
== ComboAddress("192.0.2.1:53")) {
4766 if (domain
== DNSName("com.")) {
4767 setLWResult(res
, 0, true, false, true);
4768 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4769 addRRSIG(keys
, res
->d_records
, domain
, 300);
4770 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4771 addRRSIG(keys
, res
->d_records
, domain
, 300);
4774 setLWResult(res
, 0, false, false, true);
4775 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4776 addDS(domain
, 300, res
->d_records
, keys
);
4777 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4778 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4782 else if (ip
== ComboAddress("192.0.2.2:53")) {
4783 if (type
== QType::NS
) {
4784 setLWResult(res
, 0, true, false, true);
4785 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4786 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4787 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4788 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4791 setLWResult(res
, 0, true, false, true);
4792 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4793 addRRSIG(keys
, res
->d_records
, domain
, 300);
4794 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
4795 addRRSIG(keys
, res
->d_records
, domain
, 300);
4804 vector
<DNSRecord
> ret
;
4805 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4806 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4807 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4808 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4809 BOOST_CHECK_EQUAL(queriesCount
, 8);
4811 /* again, to test the cache */
4813 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4814 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4815 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4816 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4817 BOOST_CHECK_EQUAL(queriesCount
, 8);
4820 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec
) {
4821 std::unique_ptr
<SyncRes
> sr
;
4824 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4827 const DNSName
target("nx.powerdns.com.");
4830 auto luaconfsCopy
= g_luaconfs
.getCopy();
4831 luaconfsCopy
.dsAnchors
.clear();
4832 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4833 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4834 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4836 g_luaconfs
.setState(luaconfsCopy
);
4838 size_t queriesCount
= 0;
4840 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
) {
4843 DNSName auth
= domain
;
4844 if (domain
== target
) {
4845 auth
= DNSName("powerdns.com.");
4847 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4848 if (type
== QType::DS
&& domain
== target
) {
4849 setLWResult(res
, RCode::NXDomain
, true, false, true);
4850 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4851 addRRSIG(keys
, res
->d_records
, auth
, 300);
4852 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4853 addRRSIG(keys
, res
->d_records
, auth
, 300);
4857 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4861 if (isRootServer(ip
)) {
4862 setLWResult(res
, 0, false, false, true);
4863 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4864 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4865 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4866 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4869 else if (ip
== ComboAddress("192.0.2.1:53")) {
4870 if (domain
== DNSName("com.")) {
4871 setLWResult(res
, 0, true, false, true);
4872 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4873 addRRSIG(keys
, res
->d_records
, domain
, 300);
4874 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4875 addRRSIG(keys
, res
->d_records
, domain
, 300);
4878 setLWResult(res
, 0, false, false, true);
4879 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4880 addDS(auth
, 300, res
->d_records
, keys
);
4881 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4882 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4886 else if (ip
== ComboAddress("192.0.2.2:53")) {
4887 if (type
== QType::NS
) {
4888 setLWResult(res
, 0, true, false, true);
4889 if (domain
== DNSName("powerdns.com.")) {
4890 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4891 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4892 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4893 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4896 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4897 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4898 addNSECRecordToLW(DNSName("nx.powerdns.com."), DNSName("nz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4899 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4903 setLWResult(res
, RCode::NXDomain
, true, false, true);
4904 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4905 addRRSIG(keys
, res
->d_records
, auth
, 300);
4906 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4907 addRRSIG(keys
, res
->d_records
, auth
, 300);
4908 /* add wildcard denial */
4909 addNSECRecordToLW(DNSName("powerdns.com."), DNSName("a.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4910 addRRSIG(keys
, res
->d_records
, auth
, 300);
4919 vector
<DNSRecord
> ret
;
4920 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4921 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
4922 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4923 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
4924 BOOST_CHECK_EQUAL(queriesCount
, 9);
4926 /* again, to test the cache */
4928 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4929 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
4930 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4931 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
4932 BOOST_CHECK_EQUAL(queriesCount
, 9);
4935 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard
) {
4936 std::unique_ptr
<SyncRes
> sr
;
4939 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4942 const DNSName
target("www.powerdns.com.");
4945 auto luaconfsCopy
= g_luaconfs
.getCopy();
4946 luaconfsCopy
.dsAnchors
.clear();
4947 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4948 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4949 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4951 g_luaconfs
.setState(luaconfsCopy
);
4953 size_t queriesCount
= 0;
4955 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
) {
4958 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4959 if (type
== QType::DS
&& domain
== target
) {
4960 setLWResult(res
, RCode::NoError
, true, false, true);
4961 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4962 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
4963 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
4964 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4968 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
4972 if (isRootServer(ip
)) {
4973 setLWResult(res
, 0, false, false, true);
4974 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4975 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4976 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4977 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4980 else if (ip
== ComboAddress("192.0.2.1:53")) {
4981 if (domain
== DNSName("com.")) {
4982 setLWResult(res
, 0, true, false, true);
4983 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4984 addRRSIG(keys
, res
->d_records
, domain
, 300);
4985 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4986 addRRSIG(keys
, res
->d_records
, domain
, 300);
4989 setLWResult(res
, 0, false, false, true);
4990 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4991 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
4992 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4993 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4997 else if (ip
== ComboAddress("192.0.2.2:53")) {
4998 setLWResult(res
, 0, true, false, true);
4999 if (type
== QType::NS
) {
5000 if (domain
== DNSName("powerdns.com.")) {
5001 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5002 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5003 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5004 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5007 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5008 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5009 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5010 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5014 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5015 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5016 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5017 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5018 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5027 vector
<DNSRecord
> ret
;
5028 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5029 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5030 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5031 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5032 BOOST_CHECK_EQUAL(queriesCount
, 9);
5034 /* again, to test the cache */
5036 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5037 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5038 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5039 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5040 BOOST_CHECK_EQUAL(queriesCount
, 9);
5043 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_nodata_nowildcard
) {
5044 std::unique_ptr
<SyncRes
> sr
;
5047 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5050 const DNSName
target("www.com.");
5053 auto luaconfsCopy
= g_luaconfs
.getCopy();
5054 luaconfsCopy
.dsAnchors
.clear();
5055 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5056 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5058 g_luaconfs
.setState(luaconfsCopy
);
5060 size_t queriesCount
= 0;
5062 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
) {
5065 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5066 if (type
== QType::DS
&& domain
== target
) {
5067 DNSName
auth("com.");
5068 setLWResult(res
, 0, true, false, true);
5070 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5071 addRRSIG(keys
, res
->d_records
, auth
, 300);
5072 /* add a NSEC denying the DS AND the existence of a cut (no NS) */
5073 addNSECRecordToLW(domain
, DNSName("z") + domain
, { QType::NSEC
}, 600, res
->d_records
);
5074 addRRSIG(keys
, res
->d_records
, auth
, 300);
5077 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5080 if (isRootServer(ip
)) {
5081 setLWResult(res
, 0, false, false, true);
5082 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5083 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5084 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5085 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5088 else if (ip
== ComboAddress("192.0.2.1:53")) {
5089 setLWResult(res
, 0, true, false, true);
5091 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5092 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5093 /* no record for this name */
5094 addNSECRecordToLW(DNSName("wwv.com."), DNSName("wwx.com."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5095 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5096 /* a wildcard matches but has no record for this type */
5097 addNSECRecordToLW(DNSName("*.com."), DNSName("com."), { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5098 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5106 vector
<DNSRecord
> ret
;
5107 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5108 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5109 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5110 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5111 BOOST_CHECK_EQUAL(queriesCount
, 6);
5113 /* again, to test the cache */
5115 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5116 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5117 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5118 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5119 BOOST_CHECK_EQUAL(queriesCount
, 6);
5122 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard
) {
5123 std::unique_ptr
<SyncRes
> sr
;
5126 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5129 const DNSName
target("www.com.");
5132 auto luaconfsCopy
= g_luaconfs
.getCopy();
5133 luaconfsCopy
.dsAnchors
.clear();
5134 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5135 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5137 g_luaconfs
.setState(luaconfsCopy
);
5139 size_t queriesCount
= 0;
5141 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
) {
5144 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5145 if (type
== QType::DS
&& domain
== target
) {
5146 DNSName
auth("com.");
5147 setLWResult(res
, 0, true, false, true);
5149 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5150 addRRSIG(keys
, res
->d_records
, auth
, 300);
5151 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5152 /* first the closest encloser */
5153 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5154 addRRSIG(keys
, res
->d_records
, auth
, 300);
5155 /* then the next closer */
5156 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5157 addRRSIG(keys
, res
->d_records
, auth
, 300);
5158 /* a wildcard matches but has no record for this type */
5159 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5160 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5163 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5166 if (isRootServer(ip
)) {
5167 setLWResult(res
, 0, false, false, true);
5168 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5169 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5170 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5171 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5174 else if (ip
== ComboAddress("192.0.2.1:53")) {
5175 setLWResult(res
, 0, true, false, true);
5177 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5178 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5179 /* no record for this name */
5180 /* first the closest encloser */
5181 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5182 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5183 /* then the next closer */
5184 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5185 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5186 /* a wildcard matches but has no record for this type */
5187 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5188 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5196 vector
<DNSRecord
> ret
;
5197 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5198 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5199 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5200 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5201 BOOST_CHECK_EQUAL(queriesCount
, 6);
5203 /* again, to test the cache */
5205 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5206 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5207 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5208 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5209 BOOST_CHECK_EQUAL(queriesCount
, 6);
5212 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_too_many_iterations
) {
5213 std::unique_ptr
<SyncRes
> sr
;
5216 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5219 const DNSName
target("www.com.");
5222 auto luaconfsCopy
= g_luaconfs
.getCopy();
5223 luaconfsCopy
.dsAnchors
.clear();
5224 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5225 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5227 g_luaconfs
.setState(luaconfsCopy
);
5229 size_t queriesCount
= 0;
5231 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
) {
5234 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5235 if (type
== QType::DS
&& domain
== target
) {
5236 DNSName
auth("com.");
5237 setLWResult(res
, 0, true, false, true);
5239 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5240 addRRSIG(keys
, res
->d_records
, auth
, 300);
5241 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5242 /* first the closest encloser */
5243 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5244 addRRSIG(keys
, res
->d_records
, auth
, 300);
5245 /* then the next closer */
5246 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5247 addRRSIG(keys
, res
->d_records
, auth
, 300);
5248 /* a wildcard matches but has no record for this type */
5249 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5250 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5253 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5256 if (isRootServer(ip
)) {
5257 setLWResult(res
, 0, false, false, true);
5258 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5259 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5260 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5261 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5264 else if (ip
== ComboAddress("192.0.2.1:53")) {
5265 setLWResult(res
, 0, true, false, true);
5267 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5268 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5269 /* no record for this name */
5270 /* first the closest encloser */
5271 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5272 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5273 /* then the next closer */
5274 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5275 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5276 /* a wildcard matches but has no record for this type */
5277 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5278 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5286 /* we are generating NSEC3 with more iterations than we allow, so we should go Insecure */
5287 vector
<DNSRecord
> ret
;
5288 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5289 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5290 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5291 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5292 BOOST_CHECK_EQUAL(queriesCount
, 6);
5294 /* again, to test the cache */
5296 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5297 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5298 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5299 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5300 BOOST_CHECK_EQUAL(queriesCount
, 6);
5303 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard
) {
5304 std::unique_ptr
<SyncRes
> sr
;
5307 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5310 const DNSName
target("www.powerdns.com.");
5313 auto luaconfsCopy
= g_luaconfs
.getCopy();
5314 luaconfsCopy
.dsAnchors
.clear();
5315 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5316 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5317 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5319 g_luaconfs
.setState(luaconfsCopy
);
5321 size_t queriesCount
= 0;
5323 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
) {
5326 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5327 if (type
== QType::DS
&& domain
== target
) {
5328 setLWResult(res
, RCode::NoError
, true, false, true);
5329 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5330 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5331 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5332 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5336 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5340 if (isRootServer(ip
)) {
5341 setLWResult(res
, 0, false, false, true);
5342 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5343 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5344 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5345 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5348 else if (ip
== ComboAddress("192.0.2.1:53")) {
5349 if (domain
== DNSName("com.")) {
5350 setLWResult(res
, 0, true, false, true);
5351 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5352 addRRSIG(keys
, res
->d_records
, domain
, 300);
5353 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5354 addRRSIG(keys
, res
->d_records
, domain
, 300);
5357 setLWResult(res
, 0, false, false, true);
5358 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5359 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5360 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5361 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5365 else if (ip
== ComboAddress("192.0.2.2:53")) {
5366 setLWResult(res
, 0, true, false, true);
5367 if (type
== QType::NS
) {
5368 if (domain
== DNSName("powerdns.com.")) {
5369 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5370 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5371 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5372 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5375 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5376 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5377 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5378 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5382 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5383 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5384 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5385 /* first the closest encloser */
5386 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5387 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5388 /* then the next closer */
5389 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5390 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5399 vector
<DNSRecord
> ret
;
5400 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5401 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5402 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5403 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5404 BOOST_CHECK_EQUAL(queriesCount
, 9);
5406 /* again, to test the cache */
5408 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5409 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5410 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5411 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5412 BOOST_CHECK_EQUAL(queriesCount
, 9);
5415 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard_too_many_iterations
) {
5416 std::unique_ptr
<SyncRes
> sr
;
5419 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5422 const DNSName
target("www.powerdns.com.");
5425 auto luaconfsCopy
= g_luaconfs
.getCopy();
5426 luaconfsCopy
.dsAnchors
.clear();
5427 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5428 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5429 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5431 g_luaconfs
.setState(luaconfsCopy
);
5433 size_t queriesCount
= 0;
5435 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
) {
5438 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5439 if (type
== QType::DS
&& domain
== target
) {
5440 setLWResult(res
, RCode::NoError
, true, false, true);
5441 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5442 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5443 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5444 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5448 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5452 if (isRootServer(ip
)) {
5453 setLWResult(res
, 0, false, false, true);
5454 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5455 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5456 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5457 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5460 else if (ip
== ComboAddress("192.0.2.1:53")) {
5461 if (domain
== DNSName("com.")) {
5462 setLWResult(res
, 0, true, false, true);
5463 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5464 addRRSIG(keys
, res
->d_records
, domain
, 300);
5465 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5466 addRRSIG(keys
, res
->d_records
, domain
, 300);
5469 setLWResult(res
, 0, false, false, true);
5470 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5471 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5472 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5473 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5477 else if (ip
== ComboAddress("192.0.2.2:53")) {
5478 setLWResult(res
, 0, true, false, true);
5479 if (type
== QType::NS
) {
5480 if (domain
== DNSName("powerdns.com.")) {
5481 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5482 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5483 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5484 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5487 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5488 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5489 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5490 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5494 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5495 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5496 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5497 /* first the closest encloser */
5498 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5499 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5500 /* then the next closer */
5501 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5502 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5511 /* the NSEC3 providing the denial of existence proof for the next closer has too many iterations,
5512 we should end up Insecure */
5513 vector
<DNSRecord
> ret
;
5514 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5515 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5516 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5517 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5518 BOOST_CHECK_EQUAL(queriesCount
, 9);
5520 /* again, to test the cache */
5522 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5523 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5524 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5525 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5526 BOOST_CHECK_EQUAL(queriesCount
, 9);
5529 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_missing
) {
5530 std::unique_ptr
<SyncRes
> sr
;
5533 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5536 const DNSName
target("www.powerdns.com.");
5539 auto luaconfsCopy
= g_luaconfs
.getCopy();
5540 luaconfsCopy
.dsAnchors
.clear();
5541 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5542 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5543 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5545 g_luaconfs
.setState(luaconfsCopy
);
5547 size_t queriesCount
= 0;
5549 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
) {
5552 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5553 if (type
== QType::DS
&& domain
== target
) {
5554 setLWResult(res
, RCode::NoError
, true, false, true);
5555 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5556 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5557 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5558 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5562 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5566 if (isRootServer(ip
)) {
5567 setLWResult(res
, 0, false, false, true);
5568 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5569 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5570 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5571 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5574 else if (ip
== ComboAddress("192.0.2.1:53")) {
5575 if (domain
== DNSName("com.")) {
5576 setLWResult(res
, 0, true, false, true);
5577 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5578 addRRSIG(keys
, res
->d_records
, domain
, 300);
5579 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5580 addRRSIG(keys
, res
->d_records
, domain
, 300);
5583 setLWResult(res
, 0, false, false, true);
5584 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5585 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5586 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5587 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5591 else if (ip
== ComboAddress("192.0.2.2:53")) {
5592 setLWResult(res
, 0, true, false, true);
5593 if (type
== QType::NS
) {
5594 if (domain
== DNSName("powerdns.com.")) {
5595 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5596 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5597 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5598 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5601 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5602 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5603 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5604 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5608 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5609 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5618 vector
<DNSRecord
> ret
;
5619 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5620 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5621 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5622 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5623 BOOST_CHECK_EQUAL(queriesCount
, 9);
5625 /* again, to test the cache */
5627 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5628 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5629 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5630 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5631 BOOST_CHECK_EQUAL(queriesCount
, 9);
5634 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure
) {
5635 std::unique_ptr
<SyncRes
> sr
;
5638 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5641 const DNSName
target("www.powerdns.com.");
5644 auto luaconfsCopy
= g_luaconfs
.getCopy();
5645 luaconfsCopy
.dsAnchors
.clear();
5646 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5647 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5648 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5650 g_luaconfs
.setState(luaconfsCopy
);
5652 size_t queriesCount
= 0;
5653 size_t dsQueriesCount
= 0;
5655 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
) {
5658 if (type
== QType::DS
) {
5659 DNSName
auth(domain
);
5663 setLWResult(res
, 0, true, false, true);
5664 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5665 addRRSIG(keys
, res
->d_records
, auth
, 300);
5668 else if (type
== QType::DNSKEY
) {
5669 setLWResult(res
, 0, true, false, true);
5670 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5671 addRRSIG(keys
, res
->d_records
, domain
, 300);
5675 if (isRootServer(ip
)) {
5676 setLWResult(res
, 0, false, false, true);
5677 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5678 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5679 /* No DS on referral, and no denial of the DS either */
5682 else if (ip
== ComboAddress("192.0.2.1:53")) {
5683 if (domain
== DNSName("com.")) {
5684 setLWResult(res
, 0, true, false, true);
5685 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5686 addRRSIG(keys
, res
->d_records
, domain
, 300);
5687 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5688 addRRSIG(keys
, res
->d_records
, domain
, 300);
5691 setLWResult(res
, 0, false, false, true);
5692 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5693 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5694 /* No DS on referral, and no denial of the DS either */
5698 else if (ip
== ComboAddress("192.0.2.2:53")) {
5699 setLWResult(res
, 0, true, false, true);
5700 if (type
== QType::NS
) {
5701 if (domain
== DNSName("powerdns.com.")) {
5702 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5703 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5704 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5705 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5708 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5709 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5710 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5711 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5715 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5716 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5726 vector
<DNSRecord
> ret
;
5727 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5728 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5729 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5730 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5731 BOOST_CHECK_EQUAL(queriesCount
, 9);
5732 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5734 /* again, to test the cache */
5736 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5737 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5738 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5739 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5740 BOOST_CHECK_EQUAL(queriesCount
, 9);
5741 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5744 BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop
) {
5745 std::unique_ptr
<SyncRes
> sr
;
5748 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5751 const DNSName
target("www.powerdns.com.");
5754 auto luaconfsCopy
= g_luaconfs
.getCopy();
5755 luaconfsCopy
.dsAnchors
.clear();
5756 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5757 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5758 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5759 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5761 g_luaconfs
.setState(luaconfsCopy
);
5763 size_t queriesCount
= 0;
5765 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
) {
5768 if (type
== QType::DS
) {
5769 DNSName
auth(domain
);
5772 setLWResult(res
, 0, true, false, true);
5773 if (domain
== target
) {
5774 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5775 addRRSIG(keys
, res
->d_records
, target
, 300);
5778 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5779 addRRSIG(keys
, res
->d_records
, auth
, 300);
5783 else if (type
== QType::DNSKEY
) {
5784 setLWResult(res
, 0, true, false, true);
5785 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5786 addRRSIG(keys
, res
->d_records
, domain
, 300);
5790 if (isRootServer(ip
)) {
5791 setLWResult(res
, 0, false, false, true);
5792 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5793 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5794 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5795 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5798 else if (ip
== ComboAddress("192.0.2.1:53")) {
5799 if (domain
== DNSName("com.")) {
5800 setLWResult(res
, 0, true, false, true);
5801 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5802 addRRSIG(keys
, res
->d_records
, domain
, 300);
5803 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5804 addRRSIG(keys
, res
->d_records
, domain
, 300);
5807 setLWResult(res
, 0, false, false, true);
5808 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5810 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5811 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5812 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5816 else if (ip
== ComboAddress("192.0.2.2:53")) {
5817 if (type
== QType::NS
) {
5818 if (domain
== DNSName("powerdns.com.")) {
5819 setLWResult(res
, RCode::Refused
, false, false, true);
5822 setLWResult(res
, 0, true, false, true);
5823 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5824 addRRSIG(keys
, res
->d_records
, domain
, 300);
5825 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5826 addRRSIG(keys
, res
->d_records
, domain
, 300);
5830 setLWResult(res
, 0, true, false, true);
5831 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5832 addRRSIG(keys
, res
->d_records
, DNSName("www.powerdns.com"), 300);
5842 vector
<DNSRecord
> ret
;
5843 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5844 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5845 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5846 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5847 BOOST_CHECK_EQUAL(queriesCount
, 9);
5849 /* again, to test the cache */
5851 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5852 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5853 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5854 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5855 BOOST_CHECK_EQUAL(queriesCount
, 9);
5858 BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_signed_child
) {
5859 /* check that we don't accept a signer below us */
5860 std::unique_ptr
<SyncRes
> sr
;
5863 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5866 const DNSName
target("www.powerdns.com.");
5869 auto luaconfsCopy
= g_luaconfs
.getCopy();
5870 luaconfsCopy
.dsAnchors
.clear();
5871 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5872 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5873 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5874 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5875 generateKeyMaterial(DNSName("sub.www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5877 g_luaconfs
.setState(luaconfsCopy
);
5879 size_t queriesCount
= 0;
5881 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
) {
5884 if (type
== QType::DS
) {
5885 DNSName
auth(domain
);
5888 setLWResult(res
, 0, true, false, true);
5889 if (domain
== target
) {
5890 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5891 addRRSIG(keys
, res
->d_records
, target
, 300);
5894 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5895 addRRSIG(keys
, res
->d_records
, auth
, 300);
5899 else if (type
== QType::DNSKEY
) {
5900 setLWResult(res
, 0, true, false, true);
5901 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5902 if (domain
== DNSName("www.powerdns.com.")) {
5903 addRRSIG(keys
, res
->d_records
, DNSName("sub.www.powerdns.com."), 300);
5906 addRRSIG(keys
, res
->d_records
, domain
, 300);
5911 if (isRootServer(ip
)) {
5912 setLWResult(res
, 0, false, false, true);
5913 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5914 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5915 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5916 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5919 else if (ip
== ComboAddress("192.0.2.1:53")) {
5920 if (domain
== DNSName("com.")) {
5921 setLWResult(res
, 0, true, false, true);
5922 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5923 addRRSIG(keys
, res
->d_records
, domain
, 300);
5924 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5925 addRRSIG(keys
, res
->d_records
, domain
, 300);
5928 setLWResult(res
, 0, false, false, true);
5929 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5930 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5931 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5932 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5936 else if (ip
== ComboAddress("192.0.2.2:53")) {
5937 if (type
== QType::NS
) {
5938 setLWResult(res
, 0, true, false, true);
5939 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5940 addRRSIG(keys
, res
->d_records
, domain
, 300);
5941 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5942 addRRSIG(keys
, res
->d_records
, domain
, 300);
5945 setLWResult(res
, 0, true, false, true);
5946 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5947 addRRSIG(keys
, res
->d_records
, domain
, 300);
5957 vector
<DNSRecord
> ret
;
5958 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5959 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5960 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5961 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5962 BOOST_CHECK_EQUAL(queriesCount
, 9);
5964 /* again, to test the cache */
5966 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5967 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5968 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5969 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5970 BOOST_CHECK_EQUAL(queriesCount
, 9);
5973 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure
) {
5974 std::unique_ptr
<SyncRes
> sr
;
5977 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5980 const DNSName
target("www.powerdns.com.");
5983 auto luaconfsCopy
= g_luaconfs
.getCopy();
5984 luaconfsCopy
.dsAnchors
.clear();
5985 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5986 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5988 g_luaconfs
.setState(luaconfsCopy
);
5990 size_t queriesCount
= 0;
5991 size_t dsQueriesCount
= 0;
5993 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
) {
5996 if (type
== QType::DS
) {
5997 DNSName
auth(domain
);
6001 setLWResult(res
, 0, true, false, true);
6002 if (domain
== DNSName("com.")) {
6003 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
6006 addRecordToLW(res
, "com.", QType::SOA
, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6007 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6008 addNSECRecordToLW(domain
, DNSName("powerdnt.com."), { QType::NS
}, 600, res
->d_records
);
6010 addRRSIG(keys
, res
->d_records
, auth
, 300);
6013 else if (type
== QType::DNSKEY
) {
6014 setLWResult(res
, 0, true, false, true);
6015 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6016 addRRSIG(keys
, res
->d_records
, domain
, 300);
6020 if (isRootServer(ip
)) {
6021 setLWResult(res
, 0, false, false, true);
6022 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6023 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6024 /* No DS on referral, and no denial of the DS either */
6027 else if (ip
== ComboAddress("192.0.2.1:53")) {
6028 if (domain
== DNSName("com.")) {
6029 setLWResult(res
, 0, true, false, true);
6030 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6031 addRRSIG(keys
, res
->d_records
, domain
, 300);
6032 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6033 addRRSIG(keys
, res
->d_records
, domain
, 300);
6036 setLWResult(res
, 0, false, false, true);
6037 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6038 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6039 /* No DS on referral, and no denial of the DS either */
6043 else if (ip
== ComboAddress("192.0.2.2:53")) {
6044 setLWResult(res
, 0, true, false, true);
6045 if (type
== QType::NS
) {
6046 if (domain
== DNSName("powerdns.com.")) {
6047 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6048 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6051 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6055 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
6064 vector
<DNSRecord
> ret
;
6065 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6066 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6067 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6068 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6069 BOOST_CHECK_EQUAL(queriesCount
, 7);
6070 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6072 /* again, to test the cache */
6074 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6075 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6076 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6077 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6078 BOOST_CHECK_EQUAL(queriesCount
, 7);
6079 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6082 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec
) {
6083 std::unique_ptr
<SyncRes
> sr
;
6086 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6089 const DNSName
target("powerdns.com.");
6092 auto luaconfsCopy
= g_luaconfs
.getCopy();
6093 luaconfsCopy
.dsAnchors
.clear();
6094 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6095 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6096 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6098 g_luaconfs
.setState(luaconfsCopy
);
6100 size_t queriesCount
= 0;
6102 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
) {
6105 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6106 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6109 if (isRootServer(ip
)) {
6110 setLWResult(res
, 0, false, false, true);
6111 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6112 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6113 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6114 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6117 else if (ip
== ComboAddress("192.0.2.1:53")) {
6118 if (domain
== DNSName("com.")) {
6119 setLWResult(res
, 0, true, false, true);
6120 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6121 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6122 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6125 setLWResult(res
, 0, false, false, true);
6126 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6127 addDS(domain
, 300, res
->d_records
, keys
);
6128 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6129 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6133 else if (ip
== ComboAddress("192.0.2.2:53")) {
6134 setLWResult(res
, 0, true, false, true);
6135 if (type
== QType::NS
) {
6136 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6137 addRRSIG(keys
, res
->d_records
, domain
, 300);
6140 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6141 addRRSIG(keys
, res
->d_records
, domain
, 300);
6142 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
6143 /* NO RRSIG for the NSEC record! */
6152 /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
6153 vector
<DNSRecord
> ret
;
6154 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6155 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6156 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6157 BOOST_CHECK_EQUAL(ret
.size(), 3);
6158 BOOST_CHECK_EQUAL(queriesCount
, 8);
6160 /* again, to test the cache */
6162 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6163 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6164 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6165 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6166 BOOST_CHECK_EQUAL(queriesCount
, 8);
6169 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec
) {
6170 std::unique_ptr
<SyncRes
> sr
;
6173 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6176 const DNSName
target("powerdns.com.");
6179 auto luaconfsCopy
= g_luaconfs
.getCopy();
6180 luaconfsCopy
.dsAnchors
.clear();
6181 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6182 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6183 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6185 g_luaconfs
.setState(luaconfsCopy
);
6187 size_t queriesCount
= 0;
6189 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
) {
6192 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6193 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6196 if (isRootServer(ip
)) {
6197 setLWResult(res
, 0, false, false, true);
6198 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6199 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6200 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6201 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6204 else if (ip
== ComboAddress("192.0.2.1:53")) {
6205 if (domain
== DNSName("com.")) {
6206 setLWResult(res
, 0, true, false, true);
6207 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6208 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6209 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6212 setLWResult(res
, 0, false, false, true);
6213 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6214 addDS(domain
, 300, res
->d_records
, keys
);
6215 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6216 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6220 else if (ip
== ComboAddress("192.0.2.2:53")) {
6221 setLWResult(res
, 0, true, false, true);
6222 if (type
== QType::NS
) {
6223 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6224 addRRSIG(keys
, res
->d_records
, domain
, 300);
6227 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6228 addRRSIG(keys
, res
->d_records
, domain
, 300);
6230 /* NO NSEC record! */
6239 /* no NSEC record in a secure zone, should be Bogus! */
6240 vector
<DNSRecord
> ret
;
6241 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6242 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6243 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6244 BOOST_CHECK_EQUAL(ret
.size(), 2);
6245 BOOST_CHECK_EQUAL(queriesCount
, 8);
6247 /* again, to test the cache */
6249 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6250 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6251 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6252 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6253 BOOST_CHECK_EQUAL(queriesCount
, 8);
6256 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure
) {
6257 std::unique_ptr
<SyncRes
> sr
;
6260 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6263 const DNSName
target("powerdns.com.");
6264 const ComboAddress
targetAddr("192.0.2.42");
6267 auto luaconfsCopy
= g_luaconfs
.getCopy();
6268 luaconfsCopy
.dsAnchors
.clear();
6269 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6270 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6272 g_luaconfs
.setState(luaconfsCopy
);
6274 size_t queriesCount
= 0;
6276 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
) {
6279 if (type
== QType::DS
) {
6280 if (domain
== target
) {
6281 setLWResult(res
, 0, false, false, true);
6282 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6283 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6284 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6287 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6290 else if (type
== QType::DNSKEY
) {
6291 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6292 setLWResult(res
, 0, true, false, true);
6293 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6294 addRRSIG(keys
, res
->d_records
, domain
, 300);
6298 setLWResult(res
, 0, false, false, true);
6299 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6304 if (isRootServer(ip
)) {
6305 setLWResult(res
, 0, false, false, true);
6306 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6307 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6308 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6309 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6312 else if (ip
== ComboAddress("192.0.2.1:53")) {
6313 if (domain
== DNSName("com.")) {
6314 setLWResult(res
, 0, true, false, true);
6315 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6316 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6317 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6320 setLWResult(res
, 0, false, false, true);
6321 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6323 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6324 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6325 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6329 else if (ip
== ComboAddress("192.0.2.2:53")) {
6330 setLWResult(res
, 0, true, false, true);
6331 if (type
== QType::NS
) {
6332 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6335 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString());
6344 vector
<DNSRecord
> ret
;
6345 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6346 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6347 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6348 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6349 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6350 /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
6351 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
6353 BOOST_CHECK_EQUAL(queriesCount
, 7);
6355 /* again, to test the cache */
6357 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6358 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6359 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6360 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6361 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6362 BOOST_CHECK_EQUAL(queriesCount
, 7);
6366 BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_ds
) {
6369 - parent is secure, zone is secure: DS should be secure
6371 std::unique_ptr
<SyncRes
> sr
;
6374 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6377 const DNSName
target("powerdns.com.");
6380 auto luaconfsCopy
= g_luaconfs
.getCopy();
6381 luaconfsCopy
.dsAnchors
.clear();
6382 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6383 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6384 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6386 g_luaconfs
.setState(luaconfsCopy
);
6388 size_t queriesCount
= 0;
6390 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
) {
6393 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6394 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6397 if (isRootServer(ip
)) {
6398 setLWResult(res
, 0, false, false, true);
6399 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6400 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6401 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6402 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6410 vector
<DNSRecord
> ret
;
6411 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6412 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6413 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6414 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6415 for (const auto& record
: ret
) {
6416 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6418 BOOST_CHECK_EQUAL(queriesCount
, 4);
6420 /* again, to test the cache */
6422 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6423 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6424 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6425 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6426 for (const auto& record
: ret
) {
6427 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6429 BOOST_CHECK_EQUAL(queriesCount
, 4);
6432 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_ds
) {
6435 - parent is secure, zone is insecure: DS denial should be secure
6437 std::unique_ptr
<SyncRes
> sr
;
6440 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6443 const DNSName
target("powerdns.com.");
6446 auto luaconfsCopy
= g_luaconfs
.getCopy();
6447 luaconfsCopy
.dsAnchors
.clear();
6448 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6449 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6451 g_luaconfs
.setState(luaconfsCopy
);
6453 size_t queriesCount
= 0;
6455 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
) {
6458 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6459 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6462 if (isRootServer(ip
)) {
6463 setLWResult(res
, 0, false, false, true);
6464 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6465 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6466 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6467 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6475 vector
<DNSRecord
> ret
;
6476 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6477 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6478 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6479 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6480 for (const auto& record
: ret
) {
6481 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6483 BOOST_CHECK_EQUAL(queriesCount
, 4);
6485 /* again, to test the cache */
6487 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6488 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6489 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6490 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6491 for (const auto& record
: ret
) {
6492 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6494 BOOST_CHECK_EQUAL(queriesCount
, 4);
6497 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut
) {
6498 std::unique_ptr
<SyncRes
> sr
;
6501 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6504 const DNSName
target("www.sub.powerdns.com.");
6505 const ComboAddress
targetAddr("192.0.2.42");
6508 auto luaconfsCopy
= g_luaconfs
.getCopy();
6509 luaconfsCopy
.dsAnchors
.clear();
6510 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6511 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6512 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6514 g_luaconfs
.setState(luaconfsCopy
);
6516 size_t queriesCount
= 0;
6518 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
) {
6521 if (type
== QType::DS
) {
6522 if (domain
== DNSName("sub.powerdns.com.")) {
6523 setLWResult(res
, 0, false, false, true);
6524 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6525 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6526 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6527 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6530 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6531 setLWResult(res
, 0, false, false, true);
6532 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);
6536 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6539 else if (type
== QType::DNSKEY
) {
6540 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6541 setLWResult(res
, 0, true, false, true);
6542 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6543 addRRSIG(keys
, res
->d_records
, domain
, 300);
6547 setLWResult(res
, 0, false, false, true);
6548 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6553 if (isRootServer(ip
)) {
6554 setLWResult(res
, 0, false, false, true);
6555 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6556 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6557 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6558 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6561 else if (ip
== ComboAddress("192.0.2.1:53")) {
6562 if (domain
== DNSName("com.")) {
6563 setLWResult(res
, 0, true, false, true);
6564 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6565 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6566 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6569 setLWResult(res
, 0, false, false, true);
6570 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6571 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6572 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6573 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6577 else if (ip
== ComboAddress("192.0.2.2:53")) {
6578 setLWResult(res
, 0, true, false, true);
6579 if (type
== QType::NS
) {
6580 if (domain
== DNSName("www.sub.powerdns.com.")) {
6581 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);
6583 else if (domain
== DNSName("sub.powerdns.com.")) {
6584 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6586 else if (domain
== DNSName("powerdns.com.")) {
6587 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6588 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6591 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6600 vector
<DNSRecord
> ret
;
6601 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6602 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6603 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6604 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6605 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6606 BOOST_CHECK_EQUAL(queriesCount
, 9);
6608 /* again, to test the cache */
6610 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6611 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6612 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6613 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6614 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6615 BOOST_CHECK_EQUAL(queriesCount
, 9);
6618 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut
) {
6619 std::unique_ptr
<SyncRes
> sr
;
6622 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6625 const DNSName
target("www.sub.powerdns.com.");
6626 const ComboAddress
targetAddr("192.0.2.42");
6629 auto luaconfsCopy
= g_luaconfs
.getCopy();
6630 luaconfsCopy
.dsAnchors
.clear();
6631 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6632 /* No key material for .com */
6633 /* But TA for sub.powerdns.com. */
6634 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6635 luaconfsCopy
.dsAnchors
[DNSName("sub.powerdns.com.")].insert(keys
[DNSName("sub.powerdns.com.")].second
);
6636 g_luaconfs
.setState(luaconfsCopy
);
6638 size_t queriesCount
= 0;
6640 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
) {
6643 if (type
== QType::DS
) {
6644 if (domain
== DNSName("www.sub.powerdns.com")) {
6645 setLWResult(res
, 0, false, false, true);
6646 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);
6647 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6648 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6649 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6652 setLWResult(res
, 0, false, false, true);
6654 if (domain
== DNSName("com.")) {
6655 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6657 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6658 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6661 setLWResult(res
, 0, false, false, true);
6662 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6667 else if (type
== QType::DNSKEY
) {
6668 if (domain
== g_rootdnsname
|| domain
== DNSName("sub.powerdns.com.")) {
6669 setLWResult(res
, 0, true, false, true);
6670 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6671 addRRSIG(keys
, res
->d_records
, domain
, 300);
6676 if (isRootServer(ip
)) {
6677 setLWResult(res
, 0, false, false, true);
6678 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6680 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6681 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6682 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6685 else if (ip
== ComboAddress("192.0.2.1:53")) {
6686 if (domain
== DNSName("com.")) {
6687 setLWResult(res
, 0, true, false, true);
6688 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6689 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6691 else if (domain
.isPartOf(DNSName("powerdns.com."))) {
6692 setLWResult(res
, 0, false, false, true);
6693 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6694 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6698 else if (ip
== ComboAddress("192.0.2.2:53")) {
6699 setLWResult(res
, 0, true, false, true);
6700 if (type
== QType::NS
) {
6701 if (domain
== DNSName("www.sub.powerdns.com.")) {
6702 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);
6703 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6704 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6705 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6707 else if (domain
== DNSName("sub.powerdns.com.")) {
6708 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6709 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6711 else if (domain
== DNSName("powerdns.com.")) {
6712 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6715 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6716 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6717 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6726 vector
<DNSRecord
> ret
;
6727 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6728 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6729 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6730 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6731 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6732 BOOST_CHECK_EQUAL(queriesCount
, 7);
6734 /* again, to test the cache */
6736 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6737 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6738 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6739 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6740 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6741 BOOST_CHECK_EQUAL(queriesCount
, 7);
6744 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata
) {
6745 std::unique_ptr
<SyncRes
> sr
;
6748 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6751 const DNSName
target("powerdns.com.");
6754 auto luaconfsCopy
= g_luaconfs
.getCopy();
6755 luaconfsCopy
.dsAnchors
.clear();
6756 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6757 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6759 g_luaconfs
.setState(luaconfsCopy
);
6761 size_t queriesCount
= 0;
6763 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
) {
6766 if (type
== QType::DS
) {
6767 if (domain
== target
) {
6768 setLWResult(res
, 0, false, false, true);
6769 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6770 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6771 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6775 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6778 else if (type
== QType::DNSKEY
) {
6779 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6780 setLWResult(res
, 0, true, false, true);
6781 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6782 addRRSIG(keys
, res
->d_records
, domain
, 300);
6786 setLWResult(res
, 0, false, false, true);
6787 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6792 if (isRootServer(ip
)) {
6793 setLWResult(res
, 0, false, false, true);
6794 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6795 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6796 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6797 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6800 else if (ip
== ComboAddress("192.0.2.1:53")) {
6801 if (domain
== DNSName("com.")) {
6802 setLWResult(res
, 0, true, false, true);
6803 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6804 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6805 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6806 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6809 setLWResult(res
, 0, false, false, true);
6810 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6812 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6813 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6814 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6818 else if (ip
== ComboAddress("192.0.2.2:53")) {
6819 if (type
== QType::NS
) {
6820 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6821 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6824 setLWResult(res
, 0, true, false, true);
6825 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6834 vector
<DNSRecord
> ret
;
6835 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6836 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6837 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6838 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6839 /* 4 NS (com from root, com from com, powerdns.com from com,
6840 powerdns.com from powerdns.com)
6841 2 DNSKEY (. and com., none for powerdns.com because no DS)
6844 BOOST_CHECK_EQUAL(queriesCount
, 7);
6846 /* again, to test the cache */
6848 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6849 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6850 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6851 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6852 BOOST_CHECK_EQUAL(queriesCount
, 7);
6855 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname
) {
6856 std::unique_ptr
<SyncRes
> sr
;
6859 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6862 const DNSName
target("powerdns.com.");
6863 const DNSName
targetCName("power-dns.com.");
6864 const ComboAddress
targetCNameAddr("192.0.2.42");
6867 auto luaconfsCopy
= g_luaconfs
.getCopy();
6868 luaconfsCopy
.dsAnchors
.clear();
6869 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6870 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6871 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6872 g_luaconfs
.setState(luaconfsCopy
);
6874 size_t queriesCount
= 0;
6876 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
) {
6879 if (type
== QType::DS
) {
6880 if (domain
== targetCName
) {
6881 setLWResult(res
, 0, false, false, true);
6882 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6883 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6884 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6888 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6891 else if (type
== QType::DNSKEY
) {
6892 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6893 setLWResult(res
, 0, true, false, true);
6894 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6895 addRRSIG(keys
, res
->d_records
, domain
, 300);
6899 setLWResult(res
, 0, false, false, true);
6900 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6905 if (isRootServer(ip
)) {
6906 setLWResult(res
, 0, false, false, true);
6907 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6908 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6909 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6910 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6913 else if (ip
== ComboAddress("192.0.2.1:53")) {
6914 setLWResult(res
, 0, false, false, true);
6915 if (domain
== DNSName("com.")) {
6916 setLWResult(res
, 0, true, false, true);
6917 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6918 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6919 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6920 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6923 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6924 if (domain
== DNSName("powerdns.com.")) {
6925 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6927 else if (domain
== targetCName
) {
6928 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6930 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6931 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6936 else if (ip
== ComboAddress("192.0.2.2:53")) {
6937 setLWResult(res
, 0, true, false, true);
6939 if (type
== QType::NS
) {
6940 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6941 if (domain
== DNSName("powerdns.com.")) {
6942 addRRSIG(keys
, res
->d_records
, domain
, 300);
6944 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6945 if (domain
== DNSName("powerdns.com.")) {
6946 addRRSIG(keys
, res
->d_records
, domain
, 300);
6950 if (domain
== DNSName("powerdns.com.")) {
6951 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6952 addRRSIG(keys
, res
->d_records
, domain
, 300);
6954 else if (domain
== targetCName
) {
6955 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6966 vector
<DNSRecord
> ret
;
6967 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6968 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6969 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6970 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6971 BOOST_CHECK_EQUAL(queriesCount
, 11);
6973 /* again, to test the cache */
6975 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6976 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6977 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6978 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6979 BOOST_CHECK_EQUAL(queriesCount
, 11);
6982 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname
) {
6983 std::unique_ptr
<SyncRes
> sr
;
6986 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6989 const DNSName
target("power-dns.com.");
6990 const DNSName
targetCName("powerdns.com.");
6991 const ComboAddress
targetCNameAddr("192.0.2.42");
6994 auto luaconfsCopy
= g_luaconfs
.getCopy();
6995 luaconfsCopy
.dsAnchors
.clear();
6996 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6997 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6998 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6999 g_luaconfs
.setState(luaconfsCopy
);
7001 size_t queriesCount
= 0;
7003 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
) {
7006 if (type
== QType::DS
) {
7007 if (domain
== DNSName("power-dns.com.")) {
7008 setLWResult(res
, 0, false, false, true);
7009 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7010 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7011 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7015 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7018 else if (type
== QType::DNSKEY
) {
7019 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7020 setLWResult(res
, 0, true, false, true);
7021 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7022 addRRSIG(keys
, res
->d_records
, domain
, 300);
7026 setLWResult(res
, 0, false, false, true);
7027 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7032 if (isRootServer(ip
)) {
7033 setLWResult(res
, 0, false, false, true);
7034 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7035 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7036 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7037 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7040 else if (ip
== ComboAddress("192.0.2.1:53")) {
7041 if (domain
== DNSName("com.")) {
7042 setLWResult(res
, 0, true, false, true);
7043 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7044 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7045 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7046 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7048 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7049 setLWResult(res
, 0, false, false, true);
7050 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7051 if (domain
== targetCName
) {
7052 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7054 else if (domain
== target
) {
7055 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7057 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7058 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7062 else if (ip
== ComboAddress("192.0.2.2:53")) {
7063 setLWResult(res
, 0, true, false, true);
7064 if (type
== QType::NS
) {
7065 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7066 if (domain
== DNSName("powerdns.com.")) {
7067 addRRSIG(keys
, res
->d_records
, domain
, 300);
7069 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7070 if (domain
== DNSName("powerdns.com.")) {
7071 addRRSIG(keys
, res
->d_records
, domain
, 300);
7075 if (domain
== target
) {
7076 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7078 else if (domain
== targetCName
) {
7079 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7080 addRRSIG(keys
, res
->d_records
, domain
, 300);
7090 vector
<DNSRecord
> ret
;
7091 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7092 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7093 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7094 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7095 BOOST_CHECK_EQUAL(queriesCount
, 11);
7097 /* again, to test the cache */
7099 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7100 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7101 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7102 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7103 BOOST_CHECK_EQUAL(queriesCount
, 11);
7106 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname
) {
7107 std::unique_ptr
<SyncRes
> sr
;
7110 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7113 const DNSName
target("power-dns.com.");
7114 const DNSName
targetCName("powerdns.com.");
7115 const ComboAddress
targetCNameAddr("192.0.2.42");
7118 auto luaconfsCopy
= g_luaconfs
.getCopy();
7119 luaconfsCopy
.dsAnchors
.clear();
7120 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7121 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7122 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7123 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7124 g_luaconfs
.setState(luaconfsCopy
);
7126 size_t queriesCount
= 0;
7128 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
) {
7131 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7132 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7135 if (isRootServer(ip
)) {
7136 setLWResult(res
, 0, false, false, true);
7137 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7138 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7139 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7140 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7143 else if (ip
== ComboAddress("192.0.2.1:53")) {
7144 if (domain
== DNSName("com.")) {
7145 setLWResult(res
, 0, true, false, true);
7146 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7147 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7148 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7149 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7151 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7152 setLWResult(res
, 0, false, false, true);
7153 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7154 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7155 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7156 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7160 else if (ip
== ComboAddress("192.0.2.2:53")) {
7161 setLWResult(res
, 0, true, false, true);
7162 if (type
== QType::NS
) {
7163 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7164 addRRSIG(keys
, res
->d_records
, domain
, 300);
7165 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7166 addRRSIG(keys
, res
->d_records
, domain
, 300);
7169 if (domain
== target
) {
7170 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7171 /* No RRSIG, leading to bogus */
7173 else if (domain
== targetCName
) {
7174 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7175 addRRSIG(keys
, res
->d_records
, domain
, 300);
7185 vector
<DNSRecord
> ret
;
7186 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7187 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7188 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7189 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7190 BOOST_CHECK_EQUAL(queriesCount
, 11);
7192 /* again, to test the cache */
7194 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7195 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7196 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7197 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7198 BOOST_CHECK_EQUAL(queriesCount
, 11);
7201 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname
) {
7202 std::unique_ptr
<SyncRes
> sr
;
7205 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7208 const DNSName
target("power-dns.com.");
7209 const DNSName
targetCName("powerdns.com.");
7210 const ComboAddress
targetCNameAddr("192.0.2.42");
7213 auto luaconfsCopy
= g_luaconfs
.getCopy();
7214 luaconfsCopy
.dsAnchors
.clear();
7215 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7216 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7217 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7218 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7219 g_luaconfs
.setState(luaconfsCopy
);
7221 size_t queriesCount
= 0;
7223 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
) {
7226 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7227 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7230 if (isRootServer(ip
)) {
7231 setLWResult(res
, 0, false, false, true);
7232 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7233 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7234 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7235 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7238 else if (ip
== ComboAddress("192.0.2.1:53")) {
7239 if (domain
== DNSName("com.")) {
7240 setLWResult(res
, 0, true, false, true);
7241 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7242 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7243 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7244 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7246 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7247 setLWResult(res
, 0, false, false, true);
7248 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7249 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7250 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7251 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7255 else if (ip
== ComboAddress("192.0.2.2:53")) {
7256 setLWResult(res
, 0, true, false, true);
7257 if (type
== QType::NS
) {
7258 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7259 addRRSIG(keys
, res
->d_records
, domain
, 300);
7260 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7261 addRRSIG(keys
, res
->d_records
, domain
, 300);
7264 if (domain
== target
) {
7265 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7266 addRRSIG(keys
, res
->d_records
, domain
, 300);
7268 else if (domain
== targetCName
) {
7269 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7270 /* No RRSIG, leading to bogus */
7280 vector
<DNSRecord
> ret
;
7281 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7282 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7283 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7284 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7285 BOOST_CHECK_EQUAL(queriesCount
, 11);
7287 /* again, to test the cache */
7289 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7290 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7291 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7292 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7293 BOOST_CHECK_EQUAL(queriesCount
, 11);
7296 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname
) {
7297 std::unique_ptr
<SyncRes
> sr
;
7300 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7303 const DNSName
target("power-dns.com.");
7304 const DNSName
targetCName("powerdns.com.");
7305 const ComboAddress
targetCNameAddr("192.0.2.42");
7308 auto luaconfsCopy
= g_luaconfs
.getCopy();
7309 luaconfsCopy
.dsAnchors
.clear();
7310 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7311 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7312 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7313 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7314 g_luaconfs
.setState(luaconfsCopy
);
7316 size_t queriesCount
= 0;
7318 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
) {
7321 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7322 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7325 if (isRootServer(ip
)) {
7326 setLWResult(res
, 0, false, false, true);
7327 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7328 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7329 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7330 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7333 else if (ip
== ComboAddress("192.0.2.1:53")) {
7334 if (domain
== DNSName("com.")) {
7335 setLWResult(res
, 0, true, false, true);
7336 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7337 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7338 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7339 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7341 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7342 setLWResult(res
, 0, false, false, true);
7343 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7344 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7345 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7346 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7350 else if (ip
== ComboAddress("192.0.2.2:53")) {
7351 setLWResult(res
, 0, true, false, true);
7352 if (type
== QType::NS
) {
7353 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7354 addRRSIG(keys
, res
->d_records
, domain
, 300);
7355 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7356 addRRSIG(keys
, res
->d_records
, domain
, 300);
7359 if (domain
== target
) {
7360 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7361 addRRSIG(keys
, res
->d_records
, domain
, 300);
7363 else if (domain
== targetCName
) {
7364 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7365 addRRSIG(keys
, res
->d_records
, domain
, 300);
7375 vector
<DNSRecord
> ret
;
7376 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7377 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7378 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7379 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7380 BOOST_CHECK_EQUAL(queriesCount
, 12);
7382 /* again, to test the cache */
7384 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7385 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7386 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7387 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7388 BOOST_CHECK_EQUAL(queriesCount
, 12);
7391 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname
) {
7392 std::unique_ptr
<SyncRes
> sr
;
7395 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7398 const DNSName
target("powerdns.com.");
7399 const DNSName
targetCName("power-dns.com.");
7400 const ComboAddress
targetCNameAddr("192.0.2.42");
7403 auto luaconfsCopy
= g_luaconfs
.getCopy();
7404 luaconfsCopy
.dsAnchors
.clear();
7405 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7406 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7407 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7408 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7409 g_luaconfs
.setState(luaconfsCopy
);
7411 size_t queriesCount
= 0;
7413 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
) {
7416 if (type
== QType::DS
) {
7417 if (domain
== DNSName("power-dns.com.")) {
7418 setLWResult(res
, 0, false, false, true);
7419 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7420 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7421 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7425 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7428 else if (type
== QType::DNSKEY
) {
7429 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7430 setLWResult(res
, 0, true, false, true);
7431 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7432 addRRSIG(keys
, res
->d_records
, domain
, 300);
7436 setLWResult(res
, 0, false, false, true);
7437 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7442 if (isRootServer(ip
)) {
7443 setLWResult(res
, 0, false, false, true);
7444 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7445 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7446 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7447 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7450 else if (ip
== ComboAddress("192.0.2.1:53")) {
7451 if (domain
== DNSName("com.")) {
7452 setLWResult(res
, 0, true, false, true);
7453 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7454 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7455 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7456 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7458 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7459 setLWResult(res
, 0, false, false, true);
7460 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7461 if (domain
== DNSName("powerdns.com.")) {
7462 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7464 else if (domain
== targetCName
) {
7465 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7467 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7468 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7472 else if (ip
== ComboAddress("192.0.2.2:53")) {
7473 setLWResult(res
, 0, true, false, true);
7474 if (type
== QType::NS
) {
7475 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7476 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7479 if (domain
== DNSName("powerdns.com.")) {
7480 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7481 /* No RRSIG -> Bogus */
7483 else if (domain
== targetCName
) {
7484 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7494 vector
<DNSRecord
> ret
;
7495 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7496 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7497 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7498 /* no RRSIG to show */
7499 BOOST_CHECK_EQUAL(ret
.size(), 2);
7500 BOOST_CHECK_EQUAL(queriesCount
, 10);
7502 /* again, to test the cache */
7504 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7505 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7506 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7507 BOOST_CHECK_EQUAL(ret
.size(), 2);
7508 BOOST_CHECK_EQUAL(queriesCount
, 10);
7511 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta
) {
7512 std::unique_ptr
<SyncRes
> sr
;
7515 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7518 const DNSName
target("powerdns.com.");
7519 const ComboAddress
targetAddr("192.0.2.42");
7522 auto luaconfsCopy
= g_luaconfs
.getCopy();
7523 luaconfsCopy
.dsAnchors
.clear();
7524 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7525 /* No key material for .com */
7526 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7527 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7528 g_luaconfs
.setState(luaconfsCopy
);
7530 size_t queriesCount
= 0;
7532 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
) {
7535 if (type
== QType::DNSKEY
) {
7536 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7537 setLWResult(res
, 0, true, false, true);
7538 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7539 addRRSIG(keys
, res
->d_records
, domain
, 300);
7542 else if (domain
== DNSName("com.")) {
7543 setLWResult(res
, 0, false, false, true);
7544 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7549 if (isRootServer(ip
)) {
7550 setLWResult(res
, 0, false, false, true);
7551 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7552 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7553 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7554 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7557 else if (ip
== ComboAddress("192.0.2.1:53")) {
7558 if (target
== domain
) {
7559 setLWResult(res
, 0, false, false, true);
7560 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7561 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7563 else if (domain
== DNSName("com.")) {
7564 setLWResult(res
, 0, true, false, true);
7565 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7566 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7570 else if (ip
== ComboAddress("192.0.2.2:53")) {
7571 setLWResult(res
, 0, true, false, true);
7572 if (type
== QType::NS
) {
7573 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7576 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7578 addRRSIG(keys
, res
->d_records
, domain
, 300);
7586 vector
<DNSRecord
> ret
;
7587 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7588 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7589 /* should be insecure but we have a TA for powerdns.com. */
7590 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7591 /* We got a RRSIG */
7592 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7593 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7594 BOOST_CHECK_EQUAL(queriesCount
, 5);
7596 /* again, to test the cache */
7598 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7599 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7600 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7601 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7602 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7603 BOOST_CHECK_EQUAL(queriesCount
, 5);
7606 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig
) {
7607 std::unique_ptr
<SyncRes
> sr
;
7610 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7613 const DNSName
target("powerdns.com.");
7614 const ComboAddress
targetAddr("192.0.2.42");
7617 auto luaconfsCopy
= g_luaconfs
.getCopy();
7618 luaconfsCopy
.dsAnchors
.clear();
7619 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7620 /* No key material for .com */
7621 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7622 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7623 g_luaconfs
.setState(luaconfsCopy
);
7625 size_t queriesCount
= 0;
7627 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
) {
7630 if (type
== QType::DNSKEY
) {
7631 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7632 setLWResult(res
, 0, true, false, true);
7633 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7634 addRRSIG(keys
, res
->d_records
, domain
, 300);
7637 else if (domain
== DNSName("com.")) {
7638 setLWResult(res
, 0, false, false, true);
7639 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7644 if (target
.isPartOf(domain
) && isRootServer(ip
)) {
7645 setLWResult(res
, 0, false, false, true);
7646 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7647 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7648 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7649 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7652 else if (ip
== ComboAddress("192.0.2.1:53")) {
7653 if (target
== domain
) {
7654 setLWResult(res
, 0, false, false, true);
7655 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7656 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7658 else if (domain
== DNSName("com.")) {
7659 setLWResult(res
, 0, true, false, true);
7660 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7661 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7665 else if (domain
== target
&& ip
== ComboAddress("192.0.2.2:53")) {
7666 setLWResult(res
, 0, true, false, true);
7667 if (type
== QType::NS
) {
7668 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7671 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7673 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
7681 vector
<DNSRecord
> ret
;
7682 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7683 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7684 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
7685 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7687 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7688 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7689 BOOST_CHECK_EQUAL(queriesCount
, 4);
7691 /* again, to test the cache */
7693 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7694 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7695 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7696 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7697 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7698 BOOST_CHECK_EQUAL(queriesCount
, 4);
7701 BOOST_AUTO_TEST_CASE(test_dnssec_nta
) {
7702 std::unique_ptr
<SyncRes
> sr
;
7705 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7708 const DNSName
target(".");
7711 auto luaconfsCopy
= g_luaconfs
.getCopy();
7712 luaconfsCopy
.dsAnchors
.clear();
7713 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7714 /* Add a NTA for "." */
7715 luaconfsCopy
.negAnchors
[g_rootdnsname
] = "NTA for Root";
7716 g_luaconfs
.setState(luaconfsCopy
);
7718 size_t queriesCount
= 0;
7720 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
) {
7723 if (domain
== target
&& type
== QType::NS
) {
7725 setLWResult(res
, 0, true, false, true);
7726 char addr
[] = "a.root-servers.net.";
7727 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
7729 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
7732 addRRSIG(keys
, res
->d_records
, domain
, 300);
7734 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
7735 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
7738 } else if (domain
== target
&& type
== QType::DNSKEY
) {
7740 setLWResult(res
, 0, true, false, true);
7750 vector
<DNSRecord
> ret
;
7751 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7752 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7753 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7754 /* 13 NS + 1 RRSIG */
7755 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
7756 BOOST_CHECK_EQUAL(queriesCount
, 1);
7758 /* again, to test the cache */
7760 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7761 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7762 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7763 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
7764 BOOST_CHECK_EQUAL(queriesCount
, 1);
7767 BOOST_AUTO_TEST_CASE(test_dnssec_no_ta
) {
7768 std::unique_ptr
<SyncRes
> sr
;
7771 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7774 const DNSName
target(".");
7777 /* Remove the root DS */
7778 auto luaconfsCopy
= g_luaconfs
.getCopy();
7779 luaconfsCopy
.dsAnchors
.clear();
7780 g_luaconfs
.setState(luaconfsCopy
);
7782 size_t queriesCount
= 0;
7784 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
) {
7787 if (domain
== target
&& type
== QType::NS
) {
7789 setLWResult(res
, 0, true, false, true);
7790 char addr
[] = "a.root-servers.net.";
7791 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
7793 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
7796 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
7797 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
7805 vector
<DNSRecord
> ret
;
7806 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7807 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7808 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7809 /* 13 NS + 0 RRSIG */
7810 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
7811 BOOST_CHECK_EQUAL(queriesCount
, 1);
7813 /* again, to test the cache */
7815 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7816 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7817 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7818 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
7819 BOOST_CHECK_EQUAL(queriesCount
, 1);
7822 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata
) {
7823 std::unique_ptr
<SyncRes
> sr
;
7826 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7829 const DNSName
target("powerdns.com.");
7832 auto luaconfsCopy
= g_luaconfs
.getCopy();
7833 luaconfsCopy
.dsAnchors
.clear();
7834 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7835 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7836 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7837 g_luaconfs
.setState(luaconfsCopy
);
7839 size_t queriesCount
= 0;
7841 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
) {
7844 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7845 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7849 setLWResult(res
, 0, true, false, true);
7856 vector
<DNSRecord
> ret
;
7857 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7858 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7859 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7860 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
7861 /* com|NS, powerdns.com|NS, powerdns.com|A */
7862 BOOST_CHECK_EQUAL(queriesCount
, 3);
7864 /* again, to test the cache */
7866 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7867 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7868 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7869 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
7870 /* we don't store empty results */
7871 BOOST_CHECK_EQUAL(queriesCount
, 4);
7874 BOOST_AUTO_TEST_CASE(test_nsec_denial_nowrap
) {
7878 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7880 vector
<DNSRecord
> records
;
7882 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7883 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7887 a.example.org. -> d.example.org. denies the existence of b.example.org.
7889 addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7890 recordContents
.push_back(records
.at(0).d_content
);
7891 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7892 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7895 ContentSigPair pair
;
7896 pair
.records
= recordContents
;
7897 pair
.signatures
= signatureContents
;
7899 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
7901 /* add wildcard denial */
7902 recordContents
.clear();
7903 signatureContents
.clear();
7904 addNSECRecordToLW(DNSName("example.org."), DNSName("+.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7905 recordContents
.push_back(records
.at(0).d_content
);
7906 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7907 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7910 pair
.records
= recordContents
;
7911 pair
.signatures
= signatureContents
;
7912 denialMap
[std::make_pair(DNSName("example.org."), QType::NSEC
)] = pair
;
7914 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
7915 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7917 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7918 /* let's check that d.example.org. is not denied by this proof */
7919 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7922 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_1
) {
7926 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7928 vector
<DNSRecord
> records
;
7930 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7931 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7934 Wrap case 1 test case:
7935 z.example.org. -> b.example.org. denies the existence of a.example.org.
7937 addNSECRecordToLW(DNSName("z.example.org."), DNSName("b.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7938 recordContents
.push_back(records
.at(0).d_content
);
7939 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7940 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7943 ContentSigPair pair
;
7944 pair
.records
= recordContents
;
7945 pair
.signatures
= signatureContents
;
7947 denialMap
[std::make_pair(DNSName("z.example.org."), QType::NSEC
)] = pair
;
7949 dState denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
7950 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7952 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7953 /* let's check that d.example.org. is not denied by this proof */
7954 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7957 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_2
) {
7961 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7963 vector
<DNSRecord
> records
;
7965 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7966 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7969 Wrap case 2 test case:
7970 y.example.org. -> a.example.org. denies the existence of z.example.org.
7972 addNSECRecordToLW(DNSName("y.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7973 recordContents
.push_back(records
.at(0).d_content
);
7974 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7975 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7978 ContentSigPair pair
;
7979 pair
.records
= recordContents
;
7980 pair
.signatures
= signatureContents
;
7982 denialMap
[std::make_pair(DNSName("y.example.org."), QType::NSEC
)] = pair
;
7984 dState denialState
= getDenial(denialMap
, DNSName("z.example.org."), QType::A
, false, false);
7985 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7987 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7988 /* let's check that d.example.org. is not denied by this proof */
7989 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7992 BOOST_AUTO_TEST_CASE(test_nsec_denial_only_one_nsec
) {
7996 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7998 vector
<DNSRecord
> records
;
8000 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8001 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8004 Only one NSEC in the whole zone test case:
8005 a.example.org. -> a.example.org. denies the existence of b.example.org.
8007 addNSECRecordToLW(DNSName("a.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8008 recordContents
.push_back(records
.at(0).d_content
);
8009 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8010 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8013 ContentSigPair pair
;
8014 pair
.records
= recordContents
;
8015 pair
.signatures
= signatureContents
;
8017 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
8019 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
8020 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8022 denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
8023 /* let's check that d.example.org. is not denied by this proof */
8024 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8027 BOOST_AUTO_TEST_CASE(test_nsec_root_nxd_denial
) {
8031 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8033 vector
<DNSRecord
> records
;
8035 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8036 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8039 The RRSIG from "." denies the existence of anything between a. and c.,
8042 addNSECRecordToLW(DNSName("a."), DNSName("c."), { QType::NS
}, 600, records
);
8043 recordContents
.push_back(records
.at(0).d_content
);
8044 addRRSIG(keys
, records
, DNSName("."), 300);
8045 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8048 ContentSigPair pair
;
8049 pair
.records
= recordContents
;
8050 pair
.signatures
= signatureContents
;
8052 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8054 /* add wildcard denial */
8055 recordContents
.clear();
8056 signatureContents
.clear();
8057 addNSECRecordToLW(DNSName("."), DNSName("+"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8058 recordContents
.push_back(records
.at(0).d_content
);
8059 addRRSIG(keys
, records
, DNSName("."), 300);
8060 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8063 pair
.records
= recordContents
;
8064 pair
.signatures
= signatureContents
;
8065 denialMap
[std::make_pair(DNSName("."), QType::NSEC
)] = pair
;
8067 dState denialState
= getDenial(denialMap
, DNSName("b."), QType::A
, false, false);
8068 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8071 BOOST_AUTO_TEST_CASE(test_nsec_ancestor_nxqtype_denial
) {
8075 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8077 vector
<DNSRecord
> records
;
8079 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8080 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8083 The RRSIG from "." denies the existence of any type except NS at a.
8084 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8085 signer field that is shorter than the owner name of the NSEC RR) it can't
8086 be used to deny anything except the whole name or a DS.
8088 addNSECRecordToLW(DNSName("a."), DNSName("b."), { QType::NS
}, 600, records
);
8089 recordContents
.push_back(records
.at(0).d_content
);
8090 addRRSIG(keys
, records
, DNSName("."), 300);
8091 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8094 ContentSigPair pair
;
8095 pair
.records
= recordContents
;
8096 pair
.signatures
= signatureContents
;
8098 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8100 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8101 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8102 nonexistence of any RRs below that zone cut, which include all RRs at
8103 that (original) owner name other than DS RRs, and all RRs below that
8104 owner name regardless of type.
8107 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, false);
8108 /* no data means the qname/qtype is not denied, because an ancestor
8109 delegation NSEC can only deny the DS */
8110 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8112 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8113 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8116 BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial
) {
8120 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8122 vector
<DNSRecord
> records
;
8124 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8125 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8128 * RFC 5155 section 8.9:
8129 * If there is an NSEC3 RR present in the response that matches the
8130 * delegation name, then the validator MUST ensure that the NS bit is
8131 * set and that the DS bit is not set in the Type Bit Maps field of the
8135 The RRSIG from "." denies the existence of any type at a.
8136 NS should be set if it was proving an insecure delegation, let's check that
8137 we correctly detect that it's not.
8139 addNSECRecordToLW(DNSName("a."), DNSName("b."), { }, 600, records
);
8140 recordContents
.push_back(records
.at(0).d_content
);
8141 addRRSIG(keys
, records
, DNSName("."), 300);
8142 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8145 ContentSigPair pair
;
8146 pair
.records
= recordContents
;
8147 pair
.signatures
= signatureContents
;
8149 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8151 /* Insecure because the NS is not set, so while it does
8152 denies the DS, it can't prove an insecure delegation */
8153 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8154 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8157 BOOST_AUTO_TEST_CASE(test_nsec_nxqtype_cname
) {
8161 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8163 vector
<DNSRecord
> records
;
8165 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8166 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8168 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::CNAME
}, 600, records
);
8169 recordContents
.push_back(records
.at(0).d_content
);
8170 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8171 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8174 ContentSigPair pair
;
8175 pair
.records
= recordContents
;
8176 pair
.signatures
= signatureContents
;
8178 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8180 /* this NSEC is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8181 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, true, true);
8182 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8185 BOOST_AUTO_TEST_CASE(test_nsec3_nxqtype_cname
) {
8189 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8191 vector
<DNSRecord
> records
;
8193 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8194 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8196 addNSEC3UnhashedRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::CNAME
}, 600, records
);
8197 recordContents
.push_back(records
.at(0).d_content
);
8198 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8199 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8201 ContentSigPair pair
;
8202 pair
.records
= recordContents
;
8203 pair
.signatures
= signatureContents
;
8205 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8208 /* this NSEC3 is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8209 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, false, true);
8210 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8213 BOOST_AUTO_TEST_CASE(test_nsec_nxdomain_denial_missing_wildcard
) {
8217 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8219 vector
<DNSRecord
> records
;
8221 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8222 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8224 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("d.powerdns.com"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8225 recordContents
.push_back(records
.at(0).d_content
);
8226 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8227 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8230 ContentSigPair pair
;
8231 pair
.records
= recordContents
;
8232 pair
.signatures
= signatureContents
;
8234 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8236 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8237 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8240 BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard
) {
8244 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8246 vector
<DNSRecord
> records
;
8248 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8249 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8251 addNSEC3NarrowRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8252 recordContents
.push_back(records
.at(0).d_content
);
8253 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8254 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8256 ContentSigPair pair
;
8257 pair
.records
= recordContents
;
8258 pair
.signatures
= signatureContents
;
8260 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8262 /* Add NSEC3 for the closest encloser */
8263 recordContents
.clear();
8264 signatureContents
.clear();
8266 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8267 recordContents
.push_back(records
.at(0).d_content
);
8268 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8269 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8271 pair
.records
= recordContents
;
8272 pair
.signatures
= signatureContents
;
8273 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8275 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8276 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8279 BOOST_AUTO_TEST_CASE(test_nsec_ent_denial
) {
8283 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8285 vector
<DNSRecord
> records
;
8287 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8288 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8290 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::A
}, 600, records
);
8291 recordContents
.push_back(records
.at(0).d_content
);
8292 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8293 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8296 ContentSigPair pair
;
8297 pair
.records
= recordContents
;
8298 pair
.signatures
= signatureContents
;
8300 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8302 /* this NSEC is valid to prove a NXQTYPE at c.powerdns.com because it proves that
8304 dState denialState
= getDenial(denialMap
, DNSName("c.powerdns.com."), QType::AAAA
, true, true);
8305 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8307 /* this NSEC is not valid to prove a NXQTYPE at b.powerdns.com,
8308 it could prove a NXDOMAIN if it had an additional wildcard denial */
8309 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::AAAA
, true, true);
8310 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8312 /* this NSEC is not valid to prove a NXQTYPE for QType::A at a.c.powerdns.com either */
8313 denialState
= getDenial(denialMap
, DNSName("a.c.powerdns.com."), QType::A
, true, true);
8314 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8316 /* if we add the wildcard denial proof, we should get a NXDOMAIN proof for b.powerdns.com */
8317 recordContents
.clear();
8318 signatureContents
.clear();
8319 addNSECRecordToLW(DNSName(").powerdns.com."), DNSName("+.powerdns.com."), { }, 600, records
);
8320 recordContents
.push_back(records
.at(0).d_content
);
8321 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8322 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8324 pair
.records
= recordContents
;
8325 pair
.signatures
= signatureContents
;
8326 denialMap
[std::make_pair(DNSName(").powerdns.com."), QType::NSEC
)] = pair
;
8328 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, true, false);
8329 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8332 BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial
) {
8336 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8338 vector
<DNSRecord
> records
;
8340 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8341 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8344 The RRSIG from "." denies the existence of any type except NS at a.
8345 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8346 signer field that is shorter than the owner name of the NSEC RR) it can't
8347 be used to deny anything except the whole name or a DS.
8349 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::NS
}, 600, records
);
8350 recordContents
.push_back(records
.at(0).d_content
);
8351 addRRSIG(keys
, records
, DNSName("."), 300);
8352 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8354 ContentSigPair pair
;
8355 pair
.records
= recordContents
;
8356 pair
.signatures
= signatureContents
;
8358 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8361 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8362 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8363 nonexistence of any RRs below that zone cut, which include all RRs at
8364 that (original) owner name other than DS RRs, and all RRs below that
8365 owner name regardless of type.
8368 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8369 /* no data means the qname/qtype is not denied, because an ancestor
8370 delegation NSEC3 can only deny the DS */
8371 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8373 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8374 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8377 BOOST_AUTO_TEST_CASE(test_nsec3_denial_too_many_iterations
) {
8381 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8383 vector
<DNSRecord
> records
;
8385 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8386 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8388 /* adding a NSEC3 with more iterations that we support */
8389 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::AAAA
}, 600, records
, g_maxNSEC3Iterations
+ 100);
8390 recordContents
.push_back(records
.at(0).d_content
);
8391 addRRSIG(keys
, records
, DNSName("."), 300);
8392 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8394 ContentSigPair pair
;
8395 pair
.records
= recordContents
;
8396 pair
.signatures
= signatureContents
;
8398 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8401 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8402 /* since we refuse to compute more than g_maxNSEC3Iterations iterations, it should be Insecure */
8403 BOOST_CHECK_EQUAL(denialState
, INSECURE
);
8406 BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial
) {
8410 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8412 vector
<DNSRecord
> records
;
8414 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8415 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8418 * RFC 5155 section 8.9:
8419 * If there is an NSEC3 RR present in the response that matches the
8420 * delegation name, then the validator MUST ensure that the NS bit is
8421 * set and that the DS bit is not set in the Type Bit Maps field of the
8425 The RRSIG from "." denies the existence of any type at a.
8426 NS should be set if it was proving an insecure delegation, let's check that
8427 we correctly detect that it's not.
8429 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { }, 600, records
);
8430 recordContents
.push_back(records
.at(0).d_content
);
8431 addRRSIG(keys
, records
, DNSName("."), 300);
8432 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8434 ContentSigPair pair
;
8435 pair
.records
= recordContents
;
8436 pair
.signatures
= signatureContents
;
8438 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8441 /* Insecure because the NS is not set, so while it does
8442 denies the DS, it can't prove an insecure delegation */
8443 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8444 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8447 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_negcache_validity
) {
8448 std::unique_ptr
<SyncRes
> sr
;
8451 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8454 const DNSName
target("com.");
8457 auto luaconfsCopy
= g_luaconfs
.getCopy();
8458 luaconfsCopy
.dsAnchors
.clear();
8459 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8460 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8461 g_luaconfs
.setState(luaconfsCopy
);
8463 size_t queriesCount
= 0;
8465 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
) {
8468 DNSName auth
= domain
;
8471 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8472 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8475 setLWResult(res
, RCode::NoError
, true, false, true);
8476 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8477 addRRSIG(keys
, res
->d_records
, domain
, 300);
8478 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
8479 addRRSIG(keys
, res
->d_records
, domain
, 1);
8486 const time_t now
= time(nullptr);
8487 vector
<DNSRecord
> ret
;
8488 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8489 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8490 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8491 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8492 BOOST_CHECK_EQUAL(queriesCount
, 4);
8494 /* check that the entry has not been negatively cached for longer than the RRSIG validity */
8495 NegCache::NegCacheEntry ne
;
8496 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
8497 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
8498 BOOST_CHECK_EQUAL(ne
.d_ttd
, now
+ 1);
8499 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
8500 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
8501 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
8502 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
8503 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
8505 /* again, to test the cache */
8507 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8508 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8509 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8510 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8511 BOOST_CHECK_EQUAL(queriesCount
, 4);
8514 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_cache_validity
) {
8515 std::unique_ptr
<SyncRes
> sr
;
8518 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8521 const DNSName
target("com.");
8522 const ComboAddress
targetAddr("192.0.2.42");
8525 auto luaconfsCopy
= g_luaconfs
.getCopy();
8526 luaconfsCopy
.dsAnchors
.clear();
8527 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8528 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8529 g_luaconfs
.setState(luaconfsCopy
);
8531 size_t queriesCount
= 0;
8533 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
) {
8536 DNSName auth
= domain
;
8539 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8540 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8543 setLWResult(res
, RCode::NoError
, true, false, true);
8544 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
8545 addRRSIG(keys
, res
->d_records
, domain
, 1);
8552 const time_t now
= time(nullptr);
8553 vector
<DNSRecord
> ret
;
8554 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8555 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8556 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8557 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8558 BOOST_CHECK_EQUAL(queriesCount
, 4);
8560 /* check that the entry has not been cached for longer than the RRSIG validity */
8561 const ComboAddress who
;
8562 vector
<DNSRecord
> cached
;
8563 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
8564 BOOST_REQUIRE_EQUAL(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
, &signatures
), 1);
8565 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
8566 BOOST_REQUIRE_EQUAL(signatures
.size(), 1);
8567 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), 1);
8569 /* again, to test the cache */
8571 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8572 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8573 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8574 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8575 BOOST_CHECK_EQUAL(queriesCount
, 4);
8578 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_secure
) {
8580 Validation is optional, and the first query does not ask for it,
8581 so the answer is cached as Indeterminate.
8582 The second query asks for validation, answer should be marked as
8585 std::unique_ptr
<SyncRes
> sr
;
8588 setDNSSECValidation(sr
, DNSSECMode::Process
);
8591 const DNSName
target("com.");
8594 auto luaconfsCopy
= g_luaconfs
.getCopy();
8595 luaconfsCopy
.dsAnchors
.clear();
8596 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8597 g_luaconfs
.setState(luaconfsCopy
);
8599 size_t queriesCount
= 0;
8601 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
) {
8604 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8605 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8608 if (domain
== target
&& type
== QType::A
) {
8609 setLWResult(res
, 0, true, false, true);
8610 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8611 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8619 vector
<DNSRecord
> ret
;
8620 /* first query does not require validation */
8621 sr
->setDNSSECValidationRequested(false);
8622 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8623 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8624 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8625 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8626 for (const auto& record
: ret
) {
8627 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8629 BOOST_CHECK_EQUAL(queriesCount
, 1);
8633 /* second one _does_ require validation */
8634 sr
->setDNSSECValidationRequested(true);
8635 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8636 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8637 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8638 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8639 for (const auto& record
: ret
) {
8640 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8642 BOOST_CHECK_EQUAL(queriesCount
, 3);
8645 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_insecure
) {
8647 Validation is optional, and the first query does not ask for it,
8648 so the answer is cached as Indeterminate.
8649 The second query asks for validation, answer should be marked as
8652 std::unique_ptr
<SyncRes
> sr
;
8655 setDNSSECValidation(sr
, DNSSECMode::Process
);
8658 const DNSName
target("com.");
8661 auto luaconfsCopy
= g_luaconfs
.getCopy();
8662 luaconfsCopy
.dsAnchors
.clear();
8663 g_luaconfs
.setState(luaconfsCopy
);
8665 size_t queriesCount
= 0;
8667 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
) {
8670 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8671 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8674 if (domain
== target
&& type
== QType::A
) {
8675 setLWResult(res
, 0, true, false, true);
8676 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8684 vector
<DNSRecord
> ret
;
8685 /* first query does not require validation */
8686 sr
->setDNSSECValidationRequested(false);
8687 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8688 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8689 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8690 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8691 for (const auto& record
: ret
) {
8692 BOOST_CHECK(record
.d_type
== QType::A
);
8694 BOOST_CHECK_EQUAL(queriesCount
, 1);
8698 /* second one _does_ require validation */
8699 sr
->setDNSSECValidationRequested(true);
8700 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8701 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8702 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8703 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8704 for (const auto& record
: ret
) {
8705 BOOST_CHECK(record
.d_type
== QType::A
);
8707 BOOST_CHECK_EQUAL(queriesCount
, 1);
8710 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_bogus
) {
8712 Validation is optional, and the first query does not ask for it,
8713 so the answer is cached as Indeterminate.
8714 The second query asks for validation, answer should be marked as
8717 std::unique_ptr
<SyncRes
> sr
;
8720 setDNSSECValidation(sr
, DNSSECMode::Process
);
8723 const DNSName
target("com.");
8726 auto luaconfsCopy
= g_luaconfs
.getCopy();
8727 luaconfsCopy
.dsAnchors
.clear();
8728 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8729 g_luaconfs
.setState(luaconfsCopy
);
8731 size_t queriesCount
= 0;
8733 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
) {
8736 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8737 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8740 if (domain
== target
&& type
== QType::A
) {
8741 setLWResult(res
, 0, true, false, true);
8742 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8751 vector
<DNSRecord
> ret
;
8752 /* first query does not require validation */
8753 sr
->setDNSSECValidationRequested(false);
8754 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8755 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8756 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8757 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8758 for (const auto& record
: ret
) {
8759 BOOST_CHECK(record
.d_type
== QType::A
);
8761 BOOST_CHECK_EQUAL(queriesCount
, 1);
8765 /* second one _does_ require validation */
8766 sr
->setDNSSECValidationRequested(true);
8767 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8768 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8769 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8770 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8771 for (const auto& record
: ret
) {
8772 BOOST_CHECK(record
.d_type
== QType::A
);
8774 BOOST_CHECK_EQUAL(queriesCount
, 3);
8777 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_secure
) {
8779 Validation is optional, and the first query does not ask for it,
8780 so the answer is cached as Indeterminate.
8781 The second query asks for validation, answer should be marked as
8784 std::unique_ptr
<SyncRes
> sr
;
8787 setDNSSECValidation(sr
, DNSSECMode::Process
);
8790 const DNSName
target("com.");
8791 const DNSName
cnameTarget("cname-com.");
8794 auto luaconfsCopy
= g_luaconfs
.getCopy();
8795 luaconfsCopy
.dsAnchors
.clear();
8796 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8797 g_luaconfs
.setState(luaconfsCopy
);
8799 size_t queriesCount
= 0;
8801 sr
->setAsyncCallback([target
,cnameTarget
,&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
) {
8804 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8805 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8808 if (domain
== target
&& type
== QType::A
) {
8809 setLWResult(res
, 0, true, false, true);
8810 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
8811 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8812 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8813 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8815 } else if (domain
== cnameTarget
&& type
== QType::A
) {
8816 setLWResult(res
, 0, true, false, true);
8817 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8818 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8826 vector
<DNSRecord
> ret
;
8827 /* first query does not require validation */
8828 sr
->setDNSSECValidationRequested(false);
8829 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8830 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8831 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8832 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8833 for (const auto& record
: ret
) {
8834 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8836 BOOST_CHECK_EQUAL(queriesCount
, 2);
8840 /* second one _does_ require validation */
8841 sr
->setDNSSECValidationRequested(true);
8842 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8843 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8844 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8845 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8846 for (const auto& record
: ret
) {
8847 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8849 BOOST_CHECK_EQUAL(queriesCount
, 5);
8852 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_insecure
) {
8854 Validation is optional, and the first query does not ask for it,
8855 so the answer is cached as Indeterminate.
8856 The second query asks for validation, answer should be marked as
8859 std::unique_ptr
<SyncRes
> sr
;
8862 setDNSSECValidation(sr
, DNSSECMode::Process
);
8865 const DNSName
target("com.");
8866 const DNSName
cnameTarget("cname-com.");
8869 auto luaconfsCopy
= g_luaconfs
.getCopy();
8870 luaconfsCopy
.dsAnchors
.clear();
8871 g_luaconfs
.setState(luaconfsCopy
);
8873 size_t queriesCount
= 0;
8875 sr
->setAsyncCallback([target
,cnameTarget
,&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
) {
8878 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8879 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8882 if (domain
== target
&& type
== QType::A
) {
8883 setLWResult(res
, 0, true, false, true);
8884 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
8885 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8887 } else if (domain
== cnameTarget
&& type
== QType::A
) {
8888 setLWResult(res
, 0, true, false, true);
8889 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8897 vector
<DNSRecord
> ret
;
8898 /* first query does not require validation */
8899 sr
->setDNSSECValidationRequested(false);
8900 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8901 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8902 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8903 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8904 for (const auto& record
: ret
) {
8905 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8907 BOOST_CHECK_EQUAL(queriesCount
, 2);
8911 /* second one _does_ require validation */
8912 sr
->setDNSSECValidationRequested(true);
8913 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8914 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8915 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8916 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8917 for (const auto& record
: ret
) {
8918 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8920 BOOST_CHECK_EQUAL(queriesCount
, 2);
8923 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_bogus
) {
8925 Validation is optional, and the first query does not ask for it,
8926 so the answer is cached as Indeterminate.
8927 The second query asks for validation, answer should be marked as
8930 std::unique_ptr
<SyncRes
> sr
;
8933 setDNSSECValidation(sr
, DNSSECMode::Process
);
8936 const DNSName
target("com.");
8937 const DNSName
cnameTarget("cname-com.");
8940 auto luaconfsCopy
= g_luaconfs
.getCopy();
8941 luaconfsCopy
.dsAnchors
.clear();
8942 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8943 g_luaconfs
.setState(luaconfsCopy
);
8945 size_t queriesCount
= 0;
8947 sr
->setAsyncCallback([target
,cnameTarget
,&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
) {
8950 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8951 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8954 if (domain
== target
&& type
== QType::A
) {
8955 setLWResult(res
, 0, true, false, true);
8956 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
8957 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8960 } else if (domain
== cnameTarget
&& type
== QType::A
) {
8961 setLWResult(res
, 0, true, false, true);
8962 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8971 vector
<DNSRecord
> ret
;
8972 /* first query does not require validation */
8973 sr
->setDNSSECValidationRequested(false);
8974 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8975 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8976 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8977 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8978 for (const auto& record
: ret
) {
8979 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8981 BOOST_CHECK_EQUAL(queriesCount
, 2);
8985 /* second one _does_ require validation */
8986 sr
->setDNSSECValidationRequested(true);
8987 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8988 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8989 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8990 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8991 for (const auto& record
: ret
) {
8992 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8994 BOOST_CHECK_EQUAL(queriesCount
, 5);
8997 BOOST_AUTO_TEST_CASE(test_dnssec_validation_additional_without_rrsig
) {
8999 We get a record from a secure zone in the additional section, without
9000 the corresponding RRSIG. The record should not be marked as authoritative
9001 and should be correctly validated.
9003 std::unique_ptr
<SyncRes
> sr
;
9006 setDNSSECValidation(sr
, DNSSECMode::Process
);
9009 const DNSName
target("com.");
9010 const DNSName
addTarget("nsX.com.");
9013 auto luaconfsCopy
= g_luaconfs
.getCopy();
9014 luaconfsCopy
.dsAnchors
.clear();
9015 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9016 g_luaconfs
.setState(luaconfsCopy
);
9018 size_t queriesCount
= 0;
9020 sr
->setAsyncCallback([target
,addTarget
,&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
) {
9023 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9024 if (domain
== addTarget
) {
9025 DNSName
auth(domain
);
9026 /* no DS for com, auth will be . */
9028 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, false);
9030 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9033 if (domain
== target
&& type
== QType::A
) {
9034 setLWResult(res
, 0, true, false, true);
9035 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
9036 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9037 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42", DNSResourceRecord::ADDITIONAL
);
9038 /* no RRSIG for the additional record */
9040 } else if (domain
== addTarget
&& type
== QType::A
) {
9041 setLWResult(res
, 0, true, false, true);
9042 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42");
9043 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9051 vector
<DNSRecord
> ret
;
9052 /* first query for target/A, will pick up the additional record as non-auth / unvalidated */
9053 sr
->setDNSSECValidationRequested(false);
9054 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9055 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9056 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9057 BOOST_CHECK_EQUAL(ret
.size(), 2);
9058 for (const auto& record
: ret
) {
9059 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9061 BOOST_CHECK_EQUAL(queriesCount
, 1);
9064 /* ask for the additional record directly, we should not use
9065 the non-auth one and issue a new query, properly validated */
9066 sr
->setDNSSECValidationRequested(true);
9067 res
= sr
->beginResolve(addTarget
, QType(QType::A
), QClass::IN
, ret
);
9068 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9069 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9070 BOOST_CHECK_EQUAL(ret
.size(), 2);
9071 for (const auto& record
: ret
) {
9072 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9074 BOOST_CHECK_EQUAL(queriesCount
, 5);
9077 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure
) {
9079 Validation is optional, and the first query does not ask for it,
9080 so the answer is negatively cached as Indeterminate.
9081 The second query asks for validation, answer should be marked as
9084 std::unique_ptr
<SyncRes
> sr
;
9087 setDNSSECValidation(sr
, DNSSECMode::Process
);
9090 const DNSName
target("com.");
9093 auto luaconfsCopy
= g_luaconfs
.getCopy();
9094 luaconfsCopy
.dsAnchors
.clear();
9095 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9096 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9097 g_luaconfs
.setState(luaconfsCopy
);
9099 size_t queriesCount
= 0;
9101 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
) {
9104 DNSName auth
= domain
;
9107 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9108 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9111 setLWResult(res
, RCode::NoError
, true, false, true);
9112 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9113 addRRSIG(keys
, res
->d_records
, domain
, 300);
9114 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
9115 addRRSIG(keys
, res
->d_records
, domain
, 1);
9122 vector
<DNSRecord
> ret
;
9123 /* first query does not require validation */
9124 sr
->setDNSSECValidationRequested(false);
9125 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9126 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9127 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9128 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9129 BOOST_CHECK_EQUAL(queriesCount
, 1);
9130 /* check that the entry has not been negatively cached */
9131 NegCache::NegCacheEntry ne
;
9132 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9133 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9134 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9135 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9136 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9137 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9138 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9141 /* second one _does_ require validation */
9142 sr
->setDNSSECValidationRequested(true);
9143 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9144 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9145 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9146 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9147 BOOST_CHECK_EQUAL(queriesCount
, 4);
9148 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9149 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9150 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
9151 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9152 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9153 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9154 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9157 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure_ds
) {
9159 Validation is optional, and the first query does not ask for it,
9160 so the answer is negatively cached as Indeterminate.
9161 The second query asks for validation, answer should be marked as
9163 The difference with test_dnssec_validation_from_negcache_secure is
9164 that have one more level here, so we are going to look for the proof
9165 that the DS does not exist for the last level. Since there is no cut,
9166 we should accept the fact that the NSEC denies DS and NS both.
9168 std::unique_ptr
<SyncRes
> sr
;
9171 setDNSSECValidation(sr
, DNSSECMode::Process
);
9174 const DNSName
target("www.com.");
9177 auto luaconfsCopy
= g_luaconfs
.getCopy();
9178 luaconfsCopy
.dsAnchors
.clear();
9179 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9180 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9181 g_luaconfs
.setState(luaconfsCopy
);
9183 size_t queriesCount
= 0;
9185 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
) {
9188 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9189 if (domain
== target
) {
9190 /* there is no cut */
9191 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9193 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
9199 vector
<DNSRecord
> ret
;
9200 /* first query does not require validation */
9201 sr
->setDNSSECValidationRequested(false);
9202 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9203 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9204 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9205 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9206 BOOST_CHECK_EQUAL(queriesCount
, 1);
9209 /* second one _does_ require validation */
9210 sr
->setDNSSECValidationRequested(true);
9211 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9212 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9213 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9214 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9215 BOOST_CHECK_EQUAL(queriesCount
, 4);
9218 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_insecure
) {
9220 Validation is optional, and the first query does not ask for it,
9221 so the answer is negatively cached as Indeterminate.
9222 The second query asks for validation, answer should be marked as
9225 std::unique_ptr
<SyncRes
> sr
;
9228 setDNSSECValidation(sr
, DNSSECMode::Process
);
9231 const DNSName
target("com.");
9234 auto luaconfsCopy
= g_luaconfs
.getCopy();
9235 luaconfsCopy
.dsAnchors
.clear();
9236 g_luaconfs
.setState(luaconfsCopy
);
9238 size_t queriesCount
= 0;
9240 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
) {
9243 DNSName auth
= domain
;
9246 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9247 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9250 setLWResult(res
, RCode::NoError
, true, false, true);
9251 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9258 vector
<DNSRecord
> ret
;
9259 /* first query does not require validation */
9260 sr
->setDNSSECValidationRequested(false);
9261 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9262 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9263 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9264 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9265 BOOST_CHECK_EQUAL(queriesCount
, 1);
9266 /* check that the entry has not been negatively cached */
9267 NegCache::NegCacheEntry ne
;
9268 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9269 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9270 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9271 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9272 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9273 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9274 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9277 /* second one _does_ require validation */
9278 sr
->setDNSSECValidationRequested(true);
9279 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9280 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9281 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9282 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9283 BOOST_CHECK_EQUAL(queriesCount
, 1);
9284 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9285 BOOST_CHECK_EQUAL(ne
.d_validationState
, Insecure
);
9286 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9287 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9288 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9289 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9292 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_bogus
) {
9294 Validation is optional, and the first query does not ask for it,
9295 so the answer is negatively cached as Indeterminate.
9296 The second query asks for validation, answer should be marked as
9299 std::unique_ptr
<SyncRes
> sr
;
9302 setDNSSECValidation(sr
, DNSSECMode::Process
);
9305 const DNSName
target("com.");
9308 auto luaconfsCopy
= g_luaconfs
.getCopy();
9309 luaconfsCopy
.dsAnchors
.clear();
9310 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9311 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9312 g_luaconfs
.setState(luaconfsCopy
);
9314 size_t queriesCount
= 0;
9316 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
) {
9319 DNSName auth
= domain
;
9322 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9323 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9326 setLWResult(res
, RCode::NoError
, true, false, true);
9327 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9328 addRRSIG(keys
, res
->d_records
, domain
, 300);
9336 vector
<DNSRecord
> ret
;
9337 /* first query does not require validation */
9338 sr
->setDNSSECValidationRequested(false);
9339 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9340 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9341 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9342 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9343 BOOST_CHECK_EQUAL(queriesCount
, 1);
9344 NegCache::NegCacheEntry ne
;
9345 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9346 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9347 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9348 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9349 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9350 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9351 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9354 /* second one _does_ require validation */
9355 sr
->setDNSSECValidationRequested(true);
9356 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9357 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9358 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9359 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9360 BOOST_CHECK_EQUAL(queriesCount
, 4);
9361 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9362 BOOST_CHECK_EQUAL(ne
.d_validationState
, Bogus
);
9363 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9364 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9365 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9366 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9369 BOOST_AUTO_TEST_CASE(test_lowercase_outgoing
) {
9370 g_lowercaseOutgoing
= true;
9371 std::unique_ptr
<SyncRes
> sr
;
9376 vector
<DNSName
> sentOutQnames
;
9378 const DNSName
target("WWW.POWERDNS.COM");
9379 const DNSName
cname("WWW.PowerDNS.org");
9381 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
) {
9383 sentOutQnames
.push_back(domain
);
9385 if (isRootServer(ip
)) {
9386 if (domain
== target
) {
9387 setLWResult(res
, 0, false, false, true);
9388 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
9389 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
9392 if (domain
== cname
) {
9393 setLWResult(res
, 0, false, false, true);
9394 addRecordToLW(res
, "powerdns.org.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
9395 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
9398 } else if (ip
== ComboAddress("192.0.2.1:53")) {
9399 if (domain
== target
) {
9400 setLWResult(res
, 0, true, false, false);
9401 addRecordToLW(res
, domain
, QType::CNAME
, cname
.toString());
9404 } else if (ip
== ComboAddress("192.0.2.2:53")) {
9405 if (domain
== cname
) {
9406 setLWResult(res
, 0, true, false, false);
9407 addRecordToLW(res
, domain
, QType::A
, "127.0.0.1");
9414 vector
<DNSRecord
> ret
;
9415 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9417 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9419 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9420 BOOST_CHECK_EQUAL(ret
[0].d_content
->getZoneRepresentation(), cname
.toString());
9422 BOOST_REQUIRE_EQUAL(sentOutQnames
.size(), 4);
9423 BOOST_CHECK_EQUAL(sentOutQnames
[0].toString(), target
.makeLowerCase().toString());
9424 BOOST_CHECK_EQUAL(sentOutQnames
[1].toString(), target
.makeLowerCase().toString());
9425 BOOST_CHECK_EQUAL(sentOutQnames
[2].toString(), cname
.makeLowerCase().toString());
9426 BOOST_CHECK_EQUAL(sentOutQnames
[3].toString(), cname
.makeLowerCase().toString());
9428 g_lowercaseOutgoing
= false;
9431 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo
) {
9432 std::unique_ptr
<SyncRes
> sr
;
9435 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9438 const DNSName
target("com.");
9439 testkeysset_t keys
, keys2
;
9441 auto luaconfsCopy
= g_luaconfs
.getCopy();
9442 luaconfsCopy
.dsAnchors
.clear();
9443 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9444 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9445 g_luaconfs
.setState(luaconfsCopy
);
9447 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9448 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9449 // But add the existing root key otherwise no RRSIG can be created
9450 auto rootkey
= keys
.find(g_rootdnsname
);
9451 keys2
.insert(*rootkey
);
9453 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
) {
9454 DNSName auth
= domain
;
9456 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9457 if (domain
== target
) {
9458 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9462 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9468 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9469 BOOST_CHECK_EQUAL(state
, Secure
);
9470 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9471 for (const auto& i
: ds
) {
9472 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9476 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_all_sha
) {
9477 std::unique_ptr
<SyncRes
> sr
;
9480 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9483 const DNSName
target("com.");
9484 testkeysset_t keys
, keys2
, keys3
;
9486 auto luaconfsCopy
= g_luaconfs
.getCopy();
9487 luaconfsCopy
.dsAnchors
.clear();
9488 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9489 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9490 g_luaconfs
.setState(luaconfsCopy
);
9492 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9493 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9494 // But add the existing root key otherwise no RRSIG can be created
9495 auto rootkey
= keys
.find(g_rootdnsname
);
9496 keys2
.insert(*rootkey
);
9498 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys3
);
9499 // But add the existing root key otherwise no RRSIG can be created
9500 keys3
.insert(*rootkey
);
9502 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
) {
9503 DNSName auth
= domain
;
9505 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9506 if (domain
== target
) {
9507 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9510 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9514 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9520 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9521 BOOST_CHECK_EQUAL(state
, Secure
);
9522 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9523 for (const auto& i
: ds
) {
9524 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
9528 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_two_highest
) {
9529 std::unique_ptr
<SyncRes
> sr
;
9532 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9535 const DNSName
target("com.");
9536 testkeysset_t keys
, keys2
, keys3
;
9538 auto luaconfsCopy
= g_luaconfs
.getCopy();
9539 luaconfsCopy
.dsAnchors
.clear();
9540 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9541 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9542 g_luaconfs
.setState(luaconfsCopy
);
9544 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9545 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys2
);
9546 // But add the existing root key otherwise no RRSIG can be created
9547 auto rootkey
= keys
.find(g_rootdnsname
);
9548 keys2
.insert(*rootkey
);
9550 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys3
);
9551 // But add the existing root key otherwise no RRSIG can be created
9552 keys3
.insert(*rootkey
);
9554 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
) {
9555 DNSName auth
= domain
;
9557 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9558 if (domain
== target
) {
9559 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9562 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9566 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9572 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9573 BOOST_CHECK_EQUAL(state
, Secure
);
9574 BOOST_REQUIRE_EQUAL(ds
.size(), 2);
9575 for (const auto& i
: ds
) {
9576 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9581 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha384_over_gost
) {
9582 std::unique_ptr
<SyncRes
> sr
;
9585 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9588 const DNSName
target("com.");
9589 testkeysset_t keys
, keys2
;
9591 auto luaconfsCopy
= g_luaconfs
.getCopy();
9592 luaconfsCopy
.dsAnchors
.clear();
9593 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9594 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys
);
9595 g_luaconfs
.setState(luaconfsCopy
);
9597 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9598 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9599 // But add the existing root key otherwise no RRSIG can be created
9600 auto rootkey
= keys
.find(g_rootdnsname
);
9601 keys2
.insert(*rootkey
);
9603 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
) {
9604 DNSName auth
= domain
;
9606 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9607 if (domain
== target
) {
9608 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9612 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9618 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9619 BOOST_CHECK_EQUAL(state
, Secure
);
9620 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9621 for (const auto& i
: ds
) {
9622 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
9626 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha256_over_gost
) {
9627 std::unique_ptr
<SyncRes
> sr
;
9630 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9633 const DNSName
target("com.");
9634 testkeysset_t keys
, keys2
;
9636 auto luaconfsCopy
= g_luaconfs
.getCopy();
9637 luaconfsCopy
.dsAnchors
.clear();
9638 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9639 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9640 g_luaconfs
.setState(luaconfsCopy
);
9642 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9643 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9644 // But add the existing root key otherwise no RRSIG can be created
9645 auto rootkey
= keys
.find(g_rootdnsname
);
9646 keys2
.insert(*rootkey
);
9648 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
) {
9649 DNSName auth
= domain
;
9651 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9652 if (domain
== target
) {
9653 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9657 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9663 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9664 BOOST_CHECK_EQUAL(state
, Secure
);
9665 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9666 for (const auto& i
: ds
) {
9667 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9671 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_gost_over_sha1
) {
9672 std::unique_ptr
<SyncRes
> sr
;
9675 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9678 const DNSName
target("com.");
9679 testkeysset_t keys
, keys2
;
9681 auto luaconfsCopy
= g_luaconfs
.getCopy();
9682 luaconfsCopy
.dsAnchors
.clear();
9683 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9684 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys
);
9685 g_luaconfs
.setState(luaconfsCopy
);
9687 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9688 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9689 // But add the existing root key otherwise no RRSIG can be created
9690 auto rootkey
= keys
.find(g_rootdnsname
);
9691 keys2
.insert(*rootkey
);
9693 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
) {
9694 DNSName auth
= domain
;
9696 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9697 if (domain
== target
) {
9698 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9702 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9708 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9709 BOOST_CHECK_EQUAL(state
, Secure
);
9710 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9711 for (const auto& i
: ds
) {
9712 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::GOST
);
9715 #endif // HAVE_BOTAN110
9718 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
9720 - check out of band support
9726 BOOST_AUTO_TEST_SUITE_END()