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.sub.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
.isPartOf(DNSName("sub.powerdns.com"))) {
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 if (domain
== DNSName("sub.powerdns.com")) {
5332 addNSECRecordToLW(DNSName("sub.powerdns.com."), DNSName("sud.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5334 else if (domain
== target
) {
5335 addNSECRecordToLW(DNSName("www.sub.powerdns.com."), DNSName("wwz.sub.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5337 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5341 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5345 if (isRootServer(ip
)) {
5346 setLWResult(res
, 0, false, false, true);
5347 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5348 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5349 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5350 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5353 else if (ip
== ComboAddress("192.0.2.1:53")) {
5354 if (domain
== DNSName("com.")) {
5355 setLWResult(res
, 0, true, false, true);
5356 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5357 addRRSIG(keys
, res
->d_records
, domain
, 300);
5358 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5359 addRRSIG(keys
, res
->d_records
, domain
, 300);
5362 setLWResult(res
, 0, false, false, true);
5363 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5364 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5365 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5366 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5370 else if (ip
== ComboAddress("192.0.2.2:53")) {
5371 setLWResult(res
, 0, true, false, true);
5372 if (type
== QType::NS
) {
5373 if (domain
== DNSName("powerdns.com.")) {
5374 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5375 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5376 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5377 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5380 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5381 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5382 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5383 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5387 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5388 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5389 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5390 /* first the closest encloser */
5391 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5392 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5393 /* then the next closer */
5394 addNSEC3NarrowRecordToLW(DNSName("sub.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5395 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5404 vector
<DNSRecord
> ret
;
5405 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5406 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5407 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5408 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5409 BOOST_CHECK_EQUAL(queriesCount
, 10);
5411 /* again, to test the cache */
5413 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5414 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5415 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5416 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5417 BOOST_CHECK_EQUAL(queriesCount
, 10);
5420 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard_too_many_iterations
) {
5421 std::unique_ptr
<SyncRes
> sr
;
5424 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5427 const DNSName
target("www.powerdns.com.");
5430 auto luaconfsCopy
= g_luaconfs
.getCopy();
5431 luaconfsCopy
.dsAnchors
.clear();
5432 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5433 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5434 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5436 g_luaconfs
.setState(luaconfsCopy
);
5438 size_t queriesCount
= 0;
5440 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
) {
5443 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5444 if (type
== QType::DS
&& domain
== target
) {
5445 setLWResult(res
, RCode::NoError
, true, false, true);
5446 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5447 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5448 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5449 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5453 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5457 if (isRootServer(ip
)) {
5458 setLWResult(res
, 0, false, false, true);
5459 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5460 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5461 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5462 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5465 else if (ip
== ComboAddress("192.0.2.1:53")) {
5466 if (domain
== DNSName("com.")) {
5467 setLWResult(res
, 0, true, false, true);
5468 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5469 addRRSIG(keys
, res
->d_records
, domain
, 300);
5470 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5471 addRRSIG(keys
, res
->d_records
, domain
, 300);
5474 setLWResult(res
, 0, false, false, true);
5475 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5476 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5477 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5478 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5482 else if (ip
== ComboAddress("192.0.2.2:53")) {
5483 setLWResult(res
, 0, true, false, true);
5484 if (type
== QType::NS
) {
5485 if (domain
== DNSName("powerdns.com.")) {
5486 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5487 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5488 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5489 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5492 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5493 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5494 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5495 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5499 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5500 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5501 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5502 /* first the closest encloser */
5503 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5504 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5505 /* then the next closer */
5506 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5507 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5516 /* the NSEC3 providing the denial of existence proof for the next closer has too many iterations,
5517 we should end up Insecure */
5518 vector
<DNSRecord
> ret
;
5519 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5520 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5521 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5522 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5523 BOOST_CHECK_EQUAL(queriesCount
, 9);
5525 /* again, to test the cache */
5527 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5528 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5529 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5530 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5531 BOOST_CHECK_EQUAL(queriesCount
, 9);
5534 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_missing
) {
5535 std::unique_ptr
<SyncRes
> sr
;
5538 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5541 const DNSName
target("www.powerdns.com.");
5544 auto luaconfsCopy
= g_luaconfs
.getCopy();
5545 luaconfsCopy
.dsAnchors
.clear();
5546 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5547 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5548 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5550 g_luaconfs
.setState(luaconfsCopy
);
5552 size_t queriesCount
= 0;
5554 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
) {
5557 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5558 if (type
== QType::DS
&& domain
== target
) {
5559 setLWResult(res
, RCode::NoError
, true, false, true);
5560 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5561 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5562 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5563 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5567 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5571 if (isRootServer(ip
)) {
5572 setLWResult(res
, 0, false, false, true);
5573 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5574 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5575 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5576 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5579 else if (ip
== ComboAddress("192.0.2.1:53")) {
5580 if (domain
== DNSName("com.")) {
5581 setLWResult(res
, 0, true, false, true);
5582 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5583 addRRSIG(keys
, res
->d_records
, domain
, 300);
5584 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5585 addRRSIG(keys
, res
->d_records
, domain
, 300);
5588 setLWResult(res
, 0, false, false, true);
5589 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5590 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5591 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5592 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5596 else if (ip
== ComboAddress("192.0.2.2:53")) {
5597 setLWResult(res
, 0, true, false, true);
5598 if (type
== QType::NS
) {
5599 if (domain
== DNSName("powerdns.com.")) {
5600 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5601 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5602 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5603 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5606 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5607 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5608 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5609 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5613 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5614 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5623 vector
<DNSRecord
> ret
;
5624 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5625 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5626 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5627 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5628 BOOST_CHECK_EQUAL(queriesCount
, 9);
5630 /* again, to test the cache */
5632 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5633 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5634 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5635 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5636 BOOST_CHECK_EQUAL(queriesCount
, 9);
5639 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure
) {
5640 std::unique_ptr
<SyncRes
> sr
;
5643 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5646 const DNSName
target("www.powerdns.com.");
5649 auto luaconfsCopy
= g_luaconfs
.getCopy();
5650 luaconfsCopy
.dsAnchors
.clear();
5651 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5652 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5653 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5655 g_luaconfs
.setState(luaconfsCopy
);
5657 size_t queriesCount
= 0;
5658 size_t dsQueriesCount
= 0;
5660 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
) {
5663 if (type
== QType::DS
) {
5664 DNSName
auth(domain
);
5668 setLWResult(res
, 0, true, false, true);
5669 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5670 addRRSIG(keys
, res
->d_records
, auth
, 300);
5673 else if (type
== QType::DNSKEY
) {
5674 setLWResult(res
, 0, true, false, true);
5675 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5676 addRRSIG(keys
, res
->d_records
, domain
, 300);
5680 if (isRootServer(ip
)) {
5681 setLWResult(res
, 0, false, false, true);
5682 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5683 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5684 /* No DS on referral, and no denial of the DS either */
5687 else if (ip
== ComboAddress("192.0.2.1:53")) {
5688 if (domain
== DNSName("com.")) {
5689 setLWResult(res
, 0, true, false, true);
5690 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5691 addRRSIG(keys
, res
->d_records
, domain
, 300);
5692 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5693 addRRSIG(keys
, res
->d_records
, domain
, 300);
5696 setLWResult(res
, 0, false, false, true);
5697 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5698 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5699 /* No DS on referral, and no denial of the DS either */
5703 else if (ip
== ComboAddress("192.0.2.2:53")) {
5704 setLWResult(res
, 0, true, false, true);
5705 if (type
== QType::NS
) {
5706 if (domain
== DNSName("powerdns.com.")) {
5707 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5708 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5709 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5710 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5713 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5714 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5715 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5716 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5720 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5721 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5731 vector
<DNSRecord
> ret
;
5732 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5733 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5734 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5735 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5736 BOOST_CHECK_EQUAL(queriesCount
, 9);
5737 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5739 /* again, to test the cache */
5741 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5742 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5743 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5744 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5745 BOOST_CHECK_EQUAL(queriesCount
, 9);
5746 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5749 BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop
) {
5750 std::unique_ptr
<SyncRes
> sr
;
5753 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5756 const DNSName
target("www.powerdns.com.");
5759 auto luaconfsCopy
= g_luaconfs
.getCopy();
5760 luaconfsCopy
.dsAnchors
.clear();
5761 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5762 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5763 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5764 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5766 g_luaconfs
.setState(luaconfsCopy
);
5768 size_t queriesCount
= 0;
5770 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
) {
5773 if (type
== QType::DS
) {
5774 DNSName
auth(domain
);
5777 setLWResult(res
, 0, true, false, true);
5778 if (domain
== target
) {
5779 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5780 addRRSIG(keys
, res
->d_records
, target
, 300);
5783 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5784 addRRSIG(keys
, res
->d_records
, auth
, 300);
5788 else if (type
== QType::DNSKEY
) {
5789 setLWResult(res
, 0, true, false, true);
5790 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5791 addRRSIG(keys
, res
->d_records
, domain
, 300);
5795 if (isRootServer(ip
)) {
5796 setLWResult(res
, 0, false, false, true);
5797 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5798 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5799 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5800 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5803 else if (ip
== ComboAddress("192.0.2.1:53")) {
5804 if (domain
== DNSName("com.")) {
5805 setLWResult(res
, 0, true, false, true);
5806 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5807 addRRSIG(keys
, res
->d_records
, domain
, 300);
5808 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5809 addRRSIG(keys
, res
->d_records
, domain
, 300);
5812 setLWResult(res
, 0, false, false, true);
5813 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5815 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5816 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5817 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5821 else if (ip
== ComboAddress("192.0.2.2:53")) {
5822 if (type
== QType::NS
) {
5823 if (domain
== DNSName("powerdns.com.")) {
5824 setLWResult(res
, RCode::Refused
, false, false, true);
5827 setLWResult(res
, 0, true, false, true);
5828 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5829 addRRSIG(keys
, res
->d_records
, domain
, 300);
5830 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5831 addRRSIG(keys
, res
->d_records
, domain
, 300);
5835 setLWResult(res
, 0, true, false, true);
5836 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5837 addRRSIG(keys
, res
->d_records
, DNSName("www.powerdns.com"), 300);
5847 vector
<DNSRecord
> ret
;
5848 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5849 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5850 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5851 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5852 BOOST_CHECK_EQUAL(queriesCount
, 9);
5854 /* again, to test the cache */
5856 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5857 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5858 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5859 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5860 BOOST_CHECK_EQUAL(queriesCount
, 9);
5863 BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_signed_child
) {
5864 /* check that we don't accept a signer below us */
5865 std::unique_ptr
<SyncRes
> sr
;
5868 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5871 const DNSName
target("www.powerdns.com.");
5874 auto luaconfsCopy
= g_luaconfs
.getCopy();
5875 luaconfsCopy
.dsAnchors
.clear();
5876 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5877 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5878 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5879 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5880 generateKeyMaterial(DNSName("sub.www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5882 g_luaconfs
.setState(luaconfsCopy
);
5884 size_t queriesCount
= 0;
5886 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
) {
5889 if (type
== QType::DS
) {
5890 DNSName
auth(domain
);
5893 setLWResult(res
, 0, true, false, true);
5894 if (domain
== target
) {
5895 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5896 addRRSIG(keys
, res
->d_records
, target
, 300);
5899 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5900 addRRSIG(keys
, res
->d_records
, auth
, 300);
5904 else if (type
== QType::DNSKEY
) {
5905 setLWResult(res
, 0, true, false, true);
5906 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5907 if (domain
== DNSName("www.powerdns.com.")) {
5908 addRRSIG(keys
, res
->d_records
, DNSName("sub.www.powerdns.com."), 300);
5911 addRRSIG(keys
, res
->d_records
, domain
, 300);
5916 if (isRootServer(ip
)) {
5917 setLWResult(res
, 0, false, false, true);
5918 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5919 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5920 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5921 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5924 else if (ip
== ComboAddress("192.0.2.1:53")) {
5925 if (domain
== DNSName("com.")) {
5926 setLWResult(res
, 0, true, false, true);
5927 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5928 addRRSIG(keys
, res
->d_records
, domain
, 300);
5929 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5930 addRRSIG(keys
, res
->d_records
, domain
, 300);
5933 setLWResult(res
, 0, false, false, true);
5934 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5935 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5936 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5937 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5941 else if (ip
== ComboAddress("192.0.2.2:53")) {
5942 if (type
== QType::NS
) {
5943 setLWResult(res
, 0, true, false, true);
5944 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5945 addRRSIG(keys
, res
->d_records
, domain
, 300);
5946 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5947 addRRSIG(keys
, res
->d_records
, domain
, 300);
5950 setLWResult(res
, 0, true, false, true);
5951 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5952 addRRSIG(keys
, res
->d_records
, domain
, 300);
5962 vector
<DNSRecord
> ret
;
5963 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5964 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5965 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5966 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5967 BOOST_CHECK_EQUAL(queriesCount
, 9);
5969 /* again, to test the cache */
5971 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5972 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5973 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5974 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5975 BOOST_CHECK_EQUAL(queriesCount
, 9);
5978 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure
) {
5979 std::unique_ptr
<SyncRes
> sr
;
5982 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5985 const DNSName
target("www.powerdns.com.");
5988 auto luaconfsCopy
= g_luaconfs
.getCopy();
5989 luaconfsCopy
.dsAnchors
.clear();
5990 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5991 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5993 g_luaconfs
.setState(luaconfsCopy
);
5995 size_t queriesCount
= 0;
5996 size_t dsQueriesCount
= 0;
5998 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
) {
6001 if (type
== QType::DS
) {
6002 DNSName
auth(domain
);
6006 setLWResult(res
, 0, true, false, true);
6007 if (domain
== DNSName("com.")) {
6008 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
6011 addRecordToLW(res
, "com.", QType::SOA
, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6012 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6013 addNSECRecordToLW(domain
, DNSName("powerdnt.com."), { QType::NS
}, 600, res
->d_records
);
6015 addRRSIG(keys
, res
->d_records
, auth
, 300);
6018 else if (type
== QType::DNSKEY
) {
6019 setLWResult(res
, 0, true, false, true);
6020 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6021 addRRSIG(keys
, res
->d_records
, domain
, 300);
6025 if (isRootServer(ip
)) {
6026 setLWResult(res
, 0, false, false, true);
6027 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6028 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6029 /* No DS on referral, and no denial of the DS either */
6032 else if (ip
== ComboAddress("192.0.2.1:53")) {
6033 if (domain
== DNSName("com.")) {
6034 setLWResult(res
, 0, true, false, true);
6035 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6036 addRRSIG(keys
, res
->d_records
, domain
, 300);
6037 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6038 addRRSIG(keys
, res
->d_records
, domain
, 300);
6041 setLWResult(res
, 0, false, false, true);
6042 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6043 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6044 /* No DS on referral, and no denial of the DS either */
6048 else if (ip
== ComboAddress("192.0.2.2:53")) {
6049 setLWResult(res
, 0, true, false, true);
6050 if (type
== QType::NS
) {
6051 if (domain
== DNSName("powerdns.com.")) {
6052 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6053 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6056 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6060 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
6069 vector
<DNSRecord
> ret
;
6070 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6071 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6072 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6073 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6074 BOOST_CHECK_EQUAL(queriesCount
, 7);
6075 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6077 /* again, to test the cache */
6079 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6080 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6081 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6082 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6083 BOOST_CHECK_EQUAL(queriesCount
, 7);
6084 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6087 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec
) {
6088 std::unique_ptr
<SyncRes
> sr
;
6091 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6094 const DNSName
target("powerdns.com.");
6097 auto luaconfsCopy
= g_luaconfs
.getCopy();
6098 luaconfsCopy
.dsAnchors
.clear();
6099 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6100 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6101 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6103 g_luaconfs
.setState(luaconfsCopy
);
6105 size_t queriesCount
= 0;
6107 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
) {
6110 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6111 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6114 if (isRootServer(ip
)) {
6115 setLWResult(res
, 0, false, false, true);
6116 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6117 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6118 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6119 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6122 else if (ip
== ComboAddress("192.0.2.1:53")) {
6123 if (domain
== DNSName("com.")) {
6124 setLWResult(res
, 0, true, false, true);
6125 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6126 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6127 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6130 setLWResult(res
, 0, false, false, true);
6131 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6132 addDS(domain
, 300, res
->d_records
, keys
);
6133 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6134 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6138 else if (ip
== ComboAddress("192.0.2.2:53")) {
6139 setLWResult(res
, 0, true, false, true);
6140 if (type
== QType::NS
) {
6141 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6142 addRRSIG(keys
, res
->d_records
, domain
, 300);
6145 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6146 addRRSIG(keys
, res
->d_records
, domain
, 300);
6147 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
6148 /* NO RRSIG for the NSEC record! */
6157 /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
6158 vector
<DNSRecord
> ret
;
6159 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6160 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6161 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6162 BOOST_CHECK_EQUAL(ret
.size(), 3);
6163 BOOST_CHECK_EQUAL(queriesCount
, 8);
6165 /* again, to test the cache */
6167 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6168 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6169 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6170 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6171 BOOST_CHECK_EQUAL(queriesCount
, 8);
6174 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec
) {
6175 std::unique_ptr
<SyncRes
> sr
;
6178 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6181 const DNSName
target("powerdns.com.");
6184 auto luaconfsCopy
= g_luaconfs
.getCopy();
6185 luaconfsCopy
.dsAnchors
.clear();
6186 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6187 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6188 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6190 g_luaconfs
.setState(luaconfsCopy
);
6192 size_t queriesCount
= 0;
6194 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
) {
6197 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6198 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6201 if (isRootServer(ip
)) {
6202 setLWResult(res
, 0, false, false, true);
6203 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6204 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6205 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6206 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6209 else if (ip
== ComboAddress("192.0.2.1:53")) {
6210 if (domain
== DNSName("com.")) {
6211 setLWResult(res
, 0, true, false, true);
6212 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6213 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6214 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6217 setLWResult(res
, 0, false, false, true);
6218 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6219 addDS(domain
, 300, res
->d_records
, keys
);
6220 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6221 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6225 else if (ip
== ComboAddress("192.0.2.2:53")) {
6226 setLWResult(res
, 0, true, false, true);
6227 if (type
== QType::NS
) {
6228 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6229 addRRSIG(keys
, res
->d_records
, domain
, 300);
6232 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6233 addRRSIG(keys
, res
->d_records
, domain
, 300);
6235 /* NO NSEC record! */
6244 /* no NSEC record in a secure zone, should be Bogus! */
6245 vector
<DNSRecord
> ret
;
6246 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6247 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6248 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6249 BOOST_CHECK_EQUAL(ret
.size(), 2);
6250 BOOST_CHECK_EQUAL(queriesCount
, 8);
6252 /* again, to test the cache */
6254 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6255 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6256 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6257 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6258 BOOST_CHECK_EQUAL(queriesCount
, 8);
6261 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure
) {
6262 std::unique_ptr
<SyncRes
> sr
;
6265 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6268 const DNSName
target("powerdns.com.");
6269 const ComboAddress
targetAddr("192.0.2.42");
6272 auto luaconfsCopy
= g_luaconfs
.getCopy();
6273 luaconfsCopy
.dsAnchors
.clear();
6274 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6275 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6277 g_luaconfs
.setState(luaconfsCopy
);
6279 size_t queriesCount
= 0;
6281 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
) {
6284 if (type
== QType::DS
) {
6285 if (domain
== target
) {
6286 setLWResult(res
, 0, false, false, true);
6287 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6288 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6289 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6292 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6295 else if (type
== QType::DNSKEY
) {
6296 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6297 setLWResult(res
, 0, true, false, true);
6298 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6299 addRRSIG(keys
, res
->d_records
, domain
, 300);
6303 setLWResult(res
, 0, false, false, true);
6304 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6309 if (isRootServer(ip
)) {
6310 setLWResult(res
, 0, false, false, true);
6311 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6312 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6313 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6314 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6317 else if (ip
== ComboAddress("192.0.2.1:53")) {
6318 if (domain
== DNSName("com.")) {
6319 setLWResult(res
, 0, true, false, true);
6320 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6321 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6322 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6325 setLWResult(res
, 0, false, false, true);
6326 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6328 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6329 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6330 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6334 else if (ip
== ComboAddress("192.0.2.2:53")) {
6335 setLWResult(res
, 0, true, false, true);
6336 if (type
== QType::NS
) {
6337 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6340 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString());
6349 vector
<DNSRecord
> ret
;
6350 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6351 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6352 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6353 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6354 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6355 /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
6356 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
6358 BOOST_CHECK_EQUAL(queriesCount
, 7);
6360 /* again, to test the cache */
6362 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6363 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6364 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6365 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6366 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6367 BOOST_CHECK_EQUAL(queriesCount
, 7);
6371 BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_ds
) {
6374 - parent is secure, zone is secure: DS should be secure
6376 std::unique_ptr
<SyncRes
> sr
;
6379 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6382 const DNSName
target("powerdns.com.");
6385 auto luaconfsCopy
= g_luaconfs
.getCopy();
6386 luaconfsCopy
.dsAnchors
.clear();
6387 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6388 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6389 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6391 g_luaconfs
.setState(luaconfsCopy
);
6393 size_t queriesCount
= 0;
6395 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
) {
6398 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6399 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6402 if (isRootServer(ip
)) {
6403 setLWResult(res
, 0, false, false, true);
6404 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6405 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6406 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6407 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6415 vector
<DNSRecord
> ret
;
6416 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6417 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6418 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6419 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6420 for (const auto& record
: ret
) {
6421 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6423 BOOST_CHECK_EQUAL(queriesCount
, 4);
6425 /* again, to test the cache */
6427 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6428 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6429 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6430 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6431 for (const auto& record
: ret
) {
6432 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6434 BOOST_CHECK_EQUAL(queriesCount
, 4);
6437 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_ds
) {
6440 - parent is secure, zone is insecure: DS denial should be secure
6442 std::unique_ptr
<SyncRes
> sr
;
6445 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6448 const DNSName
target("powerdns.com.");
6451 auto luaconfsCopy
= g_luaconfs
.getCopy();
6452 luaconfsCopy
.dsAnchors
.clear();
6453 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6454 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6456 g_luaconfs
.setState(luaconfsCopy
);
6458 size_t queriesCount
= 0;
6460 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
) {
6463 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6464 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6467 if (isRootServer(ip
)) {
6468 setLWResult(res
, 0, false, false, true);
6469 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6470 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6471 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6472 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6480 vector
<DNSRecord
> ret
;
6481 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6482 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6483 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6484 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6485 for (const auto& record
: ret
) {
6486 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6488 BOOST_CHECK_EQUAL(queriesCount
, 4);
6490 /* again, to test the cache */
6492 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6493 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6494 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6495 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6496 for (const auto& record
: ret
) {
6497 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6499 BOOST_CHECK_EQUAL(queriesCount
, 4);
6502 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut
) {
6503 std::unique_ptr
<SyncRes
> sr
;
6506 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6509 const DNSName
target("www.sub.powerdns.com.");
6510 const ComboAddress
targetAddr("192.0.2.42");
6513 auto luaconfsCopy
= g_luaconfs
.getCopy();
6514 luaconfsCopy
.dsAnchors
.clear();
6515 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6516 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6517 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6519 g_luaconfs
.setState(luaconfsCopy
);
6521 size_t queriesCount
= 0;
6523 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
) {
6526 if (type
== QType::DS
) {
6527 if (domain
== DNSName("sub.powerdns.com.")) {
6528 setLWResult(res
, 0, false, false, true);
6529 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6530 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6531 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6532 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6535 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6536 setLWResult(res
, 0, false, false, true);
6537 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);
6541 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6544 else if (type
== QType::DNSKEY
) {
6545 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6546 setLWResult(res
, 0, true, false, true);
6547 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6548 addRRSIG(keys
, res
->d_records
, domain
, 300);
6552 setLWResult(res
, 0, false, false, true);
6553 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6558 if (isRootServer(ip
)) {
6559 setLWResult(res
, 0, false, false, true);
6560 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6561 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6562 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6563 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6566 else if (ip
== ComboAddress("192.0.2.1:53")) {
6567 if (domain
== DNSName("com.")) {
6568 setLWResult(res
, 0, true, false, true);
6569 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6570 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6571 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6574 setLWResult(res
, 0, false, false, true);
6575 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6576 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6577 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6578 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6582 else if (ip
== ComboAddress("192.0.2.2:53")) {
6583 setLWResult(res
, 0, true, false, true);
6584 if (type
== QType::NS
) {
6585 if (domain
== DNSName("www.sub.powerdns.com.")) {
6586 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);
6588 else if (domain
== DNSName("sub.powerdns.com.")) {
6589 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6591 else if (domain
== DNSName("powerdns.com.")) {
6592 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6593 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6596 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6605 vector
<DNSRecord
> ret
;
6606 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6607 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6608 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6609 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6610 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6611 BOOST_CHECK_EQUAL(queriesCount
, 9);
6613 /* again, to test the cache */
6615 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6616 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6617 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6618 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6619 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6620 BOOST_CHECK_EQUAL(queriesCount
, 9);
6623 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut
) {
6624 std::unique_ptr
<SyncRes
> sr
;
6627 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6630 const DNSName
target("www.sub.powerdns.com.");
6631 const ComboAddress
targetAddr("192.0.2.42");
6634 auto luaconfsCopy
= g_luaconfs
.getCopy();
6635 luaconfsCopy
.dsAnchors
.clear();
6636 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6637 /* No key material for .com */
6638 /* But TA for sub.powerdns.com. */
6639 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6640 luaconfsCopy
.dsAnchors
[DNSName("sub.powerdns.com.")].insert(keys
[DNSName("sub.powerdns.com.")].second
);
6641 g_luaconfs
.setState(luaconfsCopy
);
6643 size_t queriesCount
= 0;
6645 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
) {
6648 if (type
== QType::DS
) {
6649 if (domain
== DNSName("www.sub.powerdns.com")) {
6650 setLWResult(res
, 0, false, false, true);
6651 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);
6652 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6653 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6654 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6657 setLWResult(res
, 0, false, false, true);
6659 if (domain
== DNSName("com.")) {
6660 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6662 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6663 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6666 setLWResult(res
, 0, false, false, true);
6667 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6672 else if (type
== QType::DNSKEY
) {
6673 if (domain
== g_rootdnsname
|| domain
== DNSName("sub.powerdns.com.")) {
6674 setLWResult(res
, 0, true, false, true);
6675 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6676 addRRSIG(keys
, res
->d_records
, domain
, 300);
6681 if (isRootServer(ip
)) {
6682 setLWResult(res
, 0, false, false, true);
6683 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6685 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6686 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6687 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6690 else if (ip
== ComboAddress("192.0.2.1:53")) {
6691 if (domain
== DNSName("com.")) {
6692 setLWResult(res
, 0, true, false, true);
6693 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6694 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6696 else if (domain
.isPartOf(DNSName("powerdns.com."))) {
6697 setLWResult(res
, 0, false, false, true);
6698 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6699 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6703 else if (ip
== ComboAddress("192.0.2.2:53")) {
6704 setLWResult(res
, 0, true, false, true);
6705 if (type
== QType::NS
) {
6706 if (domain
== DNSName("www.sub.powerdns.com.")) {
6707 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);
6708 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6709 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6710 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6712 else if (domain
== DNSName("sub.powerdns.com.")) {
6713 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6714 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6716 else if (domain
== DNSName("powerdns.com.")) {
6717 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6720 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6721 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6722 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6731 vector
<DNSRecord
> ret
;
6732 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6733 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6734 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6735 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6736 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6737 BOOST_CHECK_EQUAL(queriesCount
, 7);
6739 /* again, to test the cache */
6741 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6742 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6743 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6744 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6745 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6746 BOOST_CHECK_EQUAL(queriesCount
, 7);
6749 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata
) {
6750 std::unique_ptr
<SyncRes
> sr
;
6753 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6756 const DNSName
target("powerdns.com.");
6759 auto luaconfsCopy
= g_luaconfs
.getCopy();
6760 luaconfsCopy
.dsAnchors
.clear();
6761 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6762 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6764 g_luaconfs
.setState(luaconfsCopy
);
6766 size_t queriesCount
= 0;
6768 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
) {
6771 if (type
== QType::DS
) {
6772 if (domain
== target
) {
6773 setLWResult(res
, 0, false, false, true);
6774 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6775 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6776 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6780 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6783 else if (type
== QType::DNSKEY
) {
6784 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6785 setLWResult(res
, 0, true, false, true);
6786 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6787 addRRSIG(keys
, res
->d_records
, domain
, 300);
6791 setLWResult(res
, 0, false, false, true);
6792 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6797 if (isRootServer(ip
)) {
6798 setLWResult(res
, 0, false, false, true);
6799 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6800 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6801 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6802 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6805 else if (ip
== ComboAddress("192.0.2.1:53")) {
6806 if (domain
== DNSName("com.")) {
6807 setLWResult(res
, 0, true, false, true);
6808 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6809 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6810 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6811 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6814 setLWResult(res
, 0, false, false, true);
6815 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6817 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6818 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6819 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6823 else if (ip
== ComboAddress("192.0.2.2:53")) {
6824 if (type
== QType::NS
) {
6825 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6826 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6829 setLWResult(res
, 0, true, false, true);
6830 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6839 vector
<DNSRecord
> ret
;
6840 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6841 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6842 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6843 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6844 /* 4 NS (com from root, com from com, powerdns.com from com,
6845 powerdns.com from powerdns.com)
6846 2 DNSKEY (. and com., none for powerdns.com because no DS)
6849 BOOST_CHECK_EQUAL(queriesCount
, 7);
6851 /* again, to test the cache */
6853 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6854 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6855 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6856 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6857 BOOST_CHECK_EQUAL(queriesCount
, 7);
6860 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname
) {
6861 std::unique_ptr
<SyncRes
> sr
;
6864 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6867 const DNSName
target("powerdns.com.");
6868 const DNSName
targetCName("power-dns.com.");
6869 const ComboAddress
targetCNameAddr("192.0.2.42");
6872 auto luaconfsCopy
= g_luaconfs
.getCopy();
6873 luaconfsCopy
.dsAnchors
.clear();
6874 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6875 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6876 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6877 g_luaconfs
.setState(luaconfsCopy
);
6879 size_t queriesCount
= 0;
6881 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
) {
6884 if (type
== QType::DS
) {
6885 if (domain
== targetCName
) {
6886 setLWResult(res
, 0, false, false, true);
6887 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6888 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6889 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6893 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6896 else if (type
== QType::DNSKEY
) {
6897 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6898 setLWResult(res
, 0, true, false, true);
6899 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6900 addRRSIG(keys
, res
->d_records
, domain
, 300);
6904 setLWResult(res
, 0, false, false, true);
6905 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6910 if (isRootServer(ip
)) {
6911 setLWResult(res
, 0, false, false, true);
6912 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6913 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6914 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6915 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6918 else if (ip
== ComboAddress("192.0.2.1:53")) {
6919 setLWResult(res
, 0, false, false, true);
6920 if (domain
== DNSName("com.")) {
6921 setLWResult(res
, 0, true, false, true);
6922 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6923 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6924 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6925 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6928 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6929 if (domain
== DNSName("powerdns.com.")) {
6930 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6932 else if (domain
== targetCName
) {
6933 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
6935 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6936 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6941 else if (ip
== ComboAddress("192.0.2.2:53")) {
6942 setLWResult(res
, 0, true, false, true);
6944 if (type
== QType::NS
) {
6945 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6946 if (domain
== DNSName("powerdns.com.")) {
6947 addRRSIG(keys
, res
->d_records
, domain
, 300);
6949 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6950 if (domain
== DNSName("powerdns.com.")) {
6951 addRRSIG(keys
, res
->d_records
, domain
, 300);
6955 if (domain
== DNSName("powerdns.com.")) {
6956 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
6957 addRRSIG(keys
, res
->d_records
, domain
, 300);
6959 else if (domain
== targetCName
) {
6960 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
6971 vector
<DNSRecord
> ret
;
6972 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6973 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6974 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6975 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6976 BOOST_CHECK_EQUAL(queriesCount
, 11);
6978 /* again, to test the cache */
6980 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6981 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6982 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6983 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6984 BOOST_CHECK_EQUAL(queriesCount
, 11);
6987 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname
) {
6988 std::unique_ptr
<SyncRes
> sr
;
6991 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6994 const DNSName
target("power-dns.com.");
6995 const DNSName
targetCName("powerdns.com.");
6996 const ComboAddress
targetCNameAddr("192.0.2.42");
6999 auto luaconfsCopy
= g_luaconfs
.getCopy();
7000 luaconfsCopy
.dsAnchors
.clear();
7001 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7002 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7003 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7004 g_luaconfs
.setState(luaconfsCopy
);
7006 size_t queriesCount
= 0;
7008 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
) {
7011 if (type
== QType::DS
) {
7012 if (domain
== DNSName("power-dns.com.")) {
7013 setLWResult(res
, 0, false, false, true);
7014 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7015 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7016 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7020 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7023 else if (type
== QType::DNSKEY
) {
7024 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7025 setLWResult(res
, 0, true, false, true);
7026 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7027 addRRSIG(keys
, res
->d_records
, domain
, 300);
7031 setLWResult(res
, 0, false, false, true);
7032 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7037 if (isRootServer(ip
)) {
7038 setLWResult(res
, 0, false, false, true);
7039 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7040 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7041 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7042 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7045 else if (ip
== ComboAddress("192.0.2.1:53")) {
7046 if (domain
== DNSName("com.")) {
7047 setLWResult(res
, 0, true, false, true);
7048 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7049 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7050 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7051 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7053 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7054 setLWResult(res
, 0, false, false, true);
7055 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7056 if (domain
== targetCName
) {
7057 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7059 else if (domain
== target
) {
7060 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7062 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7063 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7067 else if (ip
== ComboAddress("192.0.2.2:53")) {
7068 setLWResult(res
, 0, true, false, true);
7069 if (type
== QType::NS
) {
7070 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7071 if (domain
== DNSName("powerdns.com.")) {
7072 addRRSIG(keys
, res
->d_records
, domain
, 300);
7074 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7075 if (domain
== DNSName("powerdns.com.")) {
7076 addRRSIG(keys
, res
->d_records
, domain
, 300);
7080 if (domain
== target
) {
7081 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7083 else if (domain
== targetCName
) {
7084 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7085 addRRSIG(keys
, res
->d_records
, domain
, 300);
7095 vector
<DNSRecord
> ret
;
7096 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7097 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7098 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7099 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7100 BOOST_CHECK_EQUAL(queriesCount
, 11);
7102 /* again, to test the cache */
7104 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7105 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7106 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7107 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7108 BOOST_CHECK_EQUAL(queriesCount
, 11);
7111 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname
) {
7112 std::unique_ptr
<SyncRes
> sr
;
7115 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7118 const DNSName
target("power-dns.com.");
7119 const DNSName
targetCName("powerdns.com.");
7120 const ComboAddress
targetCNameAddr("192.0.2.42");
7123 auto luaconfsCopy
= g_luaconfs
.getCopy();
7124 luaconfsCopy
.dsAnchors
.clear();
7125 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7126 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7127 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7128 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7129 g_luaconfs
.setState(luaconfsCopy
);
7131 size_t queriesCount
= 0;
7133 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
) {
7136 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7137 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7140 if (isRootServer(ip
)) {
7141 setLWResult(res
, 0, false, false, true);
7142 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7143 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7144 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7145 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7148 else if (ip
== ComboAddress("192.0.2.1:53")) {
7149 if (domain
== DNSName("com.")) {
7150 setLWResult(res
, 0, true, false, true);
7151 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7152 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7153 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7154 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7156 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7157 setLWResult(res
, 0, false, false, true);
7158 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7159 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7160 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7161 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7165 else if (ip
== ComboAddress("192.0.2.2:53")) {
7166 setLWResult(res
, 0, true, false, true);
7167 if (type
== QType::NS
) {
7168 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7169 addRRSIG(keys
, res
->d_records
, domain
, 300);
7170 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7171 addRRSIG(keys
, res
->d_records
, domain
, 300);
7174 if (domain
== target
) {
7175 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7176 /* No RRSIG, leading to bogus */
7178 else if (domain
== targetCName
) {
7179 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7180 addRRSIG(keys
, res
->d_records
, domain
, 300);
7190 vector
<DNSRecord
> ret
;
7191 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7192 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7193 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7194 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7195 BOOST_CHECK_EQUAL(queriesCount
, 11);
7197 /* again, to test the cache */
7199 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7200 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7201 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7202 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7203 BOOST_CHECK_EQUAL(queriesCount
, 11);
7206 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname
) {
7207 std::unique_ptr
<SyncRes
> sr
;
7210 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7213 const DNSName
target("power-dns.com.");
7214 const DNSName
targetCName("powerdns.com.");
7215 const ComboAddress
targetCNameAddr("192.0.2.42");
7218 auto luaconfsCopy
= g_luaconfs
.getCopy();
7219 luaconfsCopy
.dsAnchors
.clear();
7220 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7221 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7222 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7223 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7224 g_luaconfs
.setState(luaconfsCopy
);
7226 size_t queriesCount
= 0;
7228 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
) {
7231 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7232 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7235 if (isRootServer(ip
)) {
7236 setLWResult(res
, 0, false, false, true);
7237 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7238 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7239 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7240 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7243 else if (ip
== ComboAddress("192.0.2.1:53")) {
7244 if (domain
== DNSName("com.")) {
7245 setLWResult(res
, 0, true, false, true);
7246 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7247 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7248 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7249 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7251 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7252 setLWResult(res
, 0, false, false, true);
7253 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7254 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7255 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7256 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7260 else if (ip
== ComboAddress("192.0.2.2:53")) {
7261 setLWResult(res
, 0, true, false, true);
7262 if (type
== QType::NS
) {
7263 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7264 addRRSIG(keys
, res
->d_records
, domain
, 300);
7265 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7266 addRRSIG(keys
, res
->d_records
, domain
, 300);
7269 if (domain
== target
) {
7270 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7271 addRRSIG(keys
, res
->d_records
, domain
, 300);
7273 else if (domain
== targetCName
) {
7274 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7275 /* No RRSIG, leading to bogus */
7285 vector
<DNSRecord
> ret
;
7286 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7287 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7288 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7289 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7290 BOOST_CHECK_EQUAL(queriesCount
, 11);
7292 /* again, to test the cache */
7294 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7295 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7296 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7297 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7298 BOOST_CHECK_EQUAL(queriesCount
, 11);
7301 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname
) {
7302 std::unique_ptr
<SyncRes
> sr
;
7305 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7308 const DNSName
target("power-dns.com.");
7309 const DNSName
targetCName("powerdns.com.");
7310 const ComboAddress
targetCNameAddr("192.0.2.42");
7313 auto luaconfsCopy
= g_luaconfs
.getCopy();
7314 luaconfsCopy
.dsAnchors
.clear();
7315 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7316 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7317 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7318 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7319 g_luaconfs
.setState(luaconfsCopy
);
7321 size_t queriesCount
= 0;
7323 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
) {
7326 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7327 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7330 if (isRootServer(ip
)) {
7331 setLWResult(res
, 0, false, false, true);
7332 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7333 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7334 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7335 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7338 else if (ip
== ComboAddress("192.0.2.1:53")) {
7339 if (domain
== DNSName("com.")) {
7340 setLWResult(res
, 0, true, false, true);
7341 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7342 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7343 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7344 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7346 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7347 setLWResult(res
, 0, false, false, true);
7348 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7349 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7350 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7351 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7355 else if (ip
== ComboAddress("192.0.2.2:53")) {
7356 setLWResult(res
, 0, true, false, true);
7357 if (type
== QType::NS
) {
7358 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7359 addRRSIG(keys
, res
->d_records
, domain
, 300);
7360 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7361 addRRSIG(keys
, res
->d_records
, domain
, 300);
7364 if (domain
== target
) {
7365 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7366 addRRSIG(keys
, res
->d_records
, domain
, 300);
7368 else if (domain
== targetCName
) {
7369 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7370 addRRSIG(keys
, res
->d_records
, domain
, 300);
7380 vector
<DNSRecord
> ret
;
7381 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7382 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7383 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7384 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7385 BOOST_CHECK_EQUAL(queriesCount
, 12);
7387 /* again, to test the cache */
7389 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7390 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7391 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7392 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7393 BOOST_CHECK_EQUAL(queriesCount
, 12);
7396 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname
) {
7397 std::unique_ptr
<SyncRes
> sr
;
7400 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7403 const DNSName
target("powerdns.com.");
7404 const DNSName
targetCName("power-dns.com.");
7405 const ComboAddress
targetCNameAddr("192.0.2.42");
7408 auto luaconfsCopy
= g_luaconfs
.getCopy();
7409 luaconfsCopy
.dsAnchors
.clear();
7410 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7411 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7412 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7413 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7414 g_luaconfs
.setState(luaconfsCopy
);
7416 size_t queriesCount
= 0;
7418 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
) {
7421 if (type
== QType::DS
) {
7422 if (domain
== DNSName("power-dns.com.")) {
7423 setLWResult(res
, 0, false, false, true);
7424 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7425 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7426 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7430 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7433 else if (type
== QType::DNSKEY
) {
7434 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7435 setLWResult(res
, 0, true, false, true);
7436 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7437 addRRSIG(keys
, res
->d_records
, domain
, 300);
7441 setLWResult(res
, 0, false, false, true);
7442 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7447 if (isRootServer(ip
)) {
7448 setLWResult(res
, 0, false, false, true);
7449 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7450 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7451 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7452 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7455 else if (ip
== ComboAddress("192.0.2.1:53")) {
7456 if (domain
== DNSName("com.")) {
7457 setLWResult(res
, 0, true, false, true);
7458 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7459 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7460 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7461 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7463 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7464 setLWResult(res
, 0, false, false, true);
7465 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7466 if (domain
== DNSName("powerdns.com.")) {
7467 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7469 else if (domain
== targetCName
) {
7470 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7472 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7473 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7477 else if (ip
== ComboAddress("192.0.2.2:53")) {
7478 setLWResult(res
, 0, true, false, true);
7479 if (type
== QType::NS
) {
7480 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7481 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7484 if (domain
== DNSName("powerdns.com.")) {
7485 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7486 /* No RRSIG -> Bogus */
7488 else if (domain
== targetCName
) {
7489 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7499 vector
<DNSRecord
> ret
;
7500 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7501 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7502 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7503 /* no RRSIG to show */
7504 BOOST_CHECK_EQUAL(ret
.size(), 2);
7505 BOOST_CHECK_EQUAL(queriesCount
, 10);
7507 /* again, to test the cache */
7509 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7510 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7511 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7512 BOOST_CHECK_EQUAL(ret
.size(), 2);
7513 BOOST_CHECK_EQUAL(queriesCount
, 10);
7516 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta
) {
7517 std::unique_ptr
<SyncRes
> sr
;
7520 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7523 const DNSName
target("powerdns.com.");
7524 const ComboAddress
targetAddr("192.0.2.42");
7527 auto luaconfsCopy
= g_luaconfs
.getCopy();
7528 luaconfsCopy
.dsAnchors
.clear();
7529 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7530 /* No key material for .com */
7531 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7532 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7533 g_luaconfs
.setState(luaconfsCopy
);
7535 size_t queriesCount
= 0;
7537 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
) {
7540 if (type
== QType::DNSKEY
) {
7541 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7542 setLWResult(res
, 0, true, false, true);
7543 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7544 addRRSIG(keys
, res
->d_records
, domain
, 300);
7547 else if (domain
== DNSName("com.")) {
7548 setLWResult(res
, 0, false, false, true);
7549 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7554 if (isRootServer(ip
)) {
7555 setLWResult(res
, 0, false, false, true);
7556 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7557 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7558 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7559 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7562 else if (ip
== ComboAddress("192.0.2.1:53")) {
7563 if (target
== domain
) {
7564 setLWResult(res
, 0, false, false, true);
7565 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7566 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7568 else if (domain
== DNSName("com.")) {
7569 setLWResult(res
, 0, true, false, true);
7570 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7571 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7575 else if (ip
== ComboAddress("192.0.2.2:53")) {
7576 setLWResult(res
, 0, true, false, true);
7577 if (type
== QType::NS
) {
7578 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7581 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7583 addRRSIG(keys
, res
->d_records
, domain
, 300);
7591 vector
<DNSRecord
> ret
;
7592 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7593 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7594 /* should be insecure but we have a TA for powerdns.com. */
7595 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7596 /* We got a RRSIG */
7597 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7598 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7599 BOOST_CHECK_EQUAL(queriesCount
, 5);
7601 /* again, to test the cache */
7603 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7604 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7605 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7606 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7607 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7608 BOOST_CHECK_EQUAL(queriesCount
, 5);
7611 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig
) {
7612 std::unique_ptr
<SyncRes
> sr
;
7615 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7618 const DNSName
target("powerdns.com.");
7619 const ComboAddress
targetAddr("192.0.2.42");
7622 auto luaconfsCopy
= g_luaconfs
.getCopy();
7623 luaconfsCopy
.dsAnchors
.clear();
7624 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7625 /* No key material for .com */
7626 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7627 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7628 g_luaconfs
.setState(luaconfsCopy
);
7630 size_t queriesCount
= 0;
7632 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
) {
7635 if (type
== QType::DNSKEY
) {
7636 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7637 setLWResult(res
, 0, true, false, true);
7638 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7639 addRRSIG(keys
, res
->d_records
, domain
, 300);
7642 else if (domain
== DNSName("com.")) {
7643 setLWResult(res
, 0, false, false, true);
7644 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7649 if (target
.isPartOf(domain
) && isRootServer(ip
)) {
7650 setLWResult(res
, 0, false, false, true);
7651 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7652 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7653 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7654 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7657 else if (ip
== ComboAddress("192.0.2.1:53")) {
7658 if (target
== domain
) {
7659 setLWResult(res
, 0, false, false, true);
7660 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7661 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7663 else if (domain
== DNSName("com.")) {
7664 setLWResult(res
, 0, true, false, true);
7665 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7666 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7670 else if (domain
== target
&& ip
== ComboAddress("192.0.2.2:53")) {
7671 setLWResult(res
, 0, true, false, true);
7672 if (type
== QType::NS
) {
7673 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7676 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7678 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
7686 vector
<DNSRecord
> ret
;
7687 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7688 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7689 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
7690 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7692 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7693 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7694 BOOST_CHECK_EQUAL(queriesCount
, 4);
7696 /* again, to test the cache */
7698 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7699 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7700 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7701 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7702 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7703 BOOST_CHECK_EQUAL(queriesCount
, 4);
7706 BOOST_AUTO_TEST_CASE(test_dnssec_nta
) {
7707 std::unique_ptr
<SyncRes
> sr
;
7710 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7713 const DNSName
target(".");
7716 auto luaconfsCopy
= g_luaconfs
.getCopy();
7717 luaconfsCopy
.dsAnchors
.clear();
7718 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7719 /* Add a NTA for "." */
7720 luaconfsCopy
.negAnchors
[g_rootdnsname
] = "NTA for Root";
7721 g_luaconfs
.setState(luaconfsCopy
);
7723 size_t queriesCount
= 0;
7725 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
) {
7728 if (domain
== target
&& type
== QType::NS
) {
7730 setLWResult(res
, 0, true, false, true);
7731 char addr
[] = "a.root-servers.net.";
7732 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
7734 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
7737 addRRSIG(keys
, res
->d_records
, domain
, 300);
7739 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
7740 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
7743 } else if (domain
== target
&& type
== QType::DNSKEY
) {
7745 setLWResult(res
, 0, true, false, true);
7755 vector
<DNSRecord
> ret
;
7756 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7757 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7758 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7759 /* 13 NS + 1 RRSIG */
7760 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
7761 BOOST_CHECK_EQUAL(queriesCount
, 1);
7763 /* again, to test the cache */
7765 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7766 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7767 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7768 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
7769 BOOST_CHECK_EQUAL(queriesCount
, 1);
7772 BOOST_AUTO_TEST_CASE(test_dnssec_no_ta
) {
7773 std::unique_ptr
<SyncRes
> sr
;
7776 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7779 const DNSName
target(".");
7782 /* Remove the root DS */
7783 auto luaconfsCopy
= g_luaconfs
.getCopy();
7784 luaconfsCopy
.dsAnchors
.clear();
7785 g_luaconfs
.setState(luaconfsCopy
);
7787 size_t queriesCount
= 0;
7789 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
) {
7792 if (domain
== target
&& type
== QType::NS
) {
7794 setLWResult(res
, 0, true, false, true);
7795 char addr
[] = "a.root-servers.net.";
7796 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
7798 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
7801 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
7802 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
7810 vector
<DNSRecord
> ret
;
7811 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7812 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7813 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7814 /* 13 NS + 0 RRSIG */
7815 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
7816 BOOST_CHECK_EQUAL(queriesCount
, 1);
7818 /* again, to test the cache */
7820 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
7821 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7822 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7823 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
7824 BOOST_CHECK_EQUAL(queriesCount
, 1);
7827 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata
) {
7828 std::unique_ptr
<SyncRes
> sr
;
7831 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7834 const DNSName
target("powerdns.com.");
7837 auto luaconfsCopy
= g_luaconfs
.getCopy();
7838 luaconfsCopy
.dsAnchors
.clear();
7839 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7840 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7841 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7842 g_luaconfs
.setState(luaconfsCopy
);
7844 size_t queriesCount
= 0;
7846 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
) {
7849 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7850 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7854 setLWResult(res
, 0, true, false, true);
7861 vector
<DNSRecord
> ret
;
7862 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7863 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7864 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7865 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
7866 /* com|NS, powerdns.com|NS, powerdns.com|A */
7867 BOOST_CHECK_EQUAL(queriesCount
, 3);
7869 /* again, to test the cache */
7871 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7872 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7873 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7874 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
7875 /* we don't store empty results */
7876 BOOST_CHECK_EQUAL(queriesCount
, 4);
7879 BOOST_AUTO_TEST_CASE(test_nsec_denial_nowrap
) {
7883 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7885 vector
<DNSRecord
> records
;
7887 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7888 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7892 a.example.org. -> d.example.org. denies the existence of b.example.org.
7894 addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7895 recordContents
.push_back(records
.at(0).d_content
);
7896 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7897 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7900 ContentSigPair pair
;
7901 pair
.records
= recordContents
;
7902 pair
.signatures
= signatureContents
;
7904 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
7906 /* add wildcard denial */
7907 recordContents
.clear();
7908 signatureContents
.clear();
7909 addNSECRecordToLW(DNSName("example.org."), DNSName("+.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7910 recordContents
.push_back(records
.at(0).d_content
);
7911 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7912 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7915 pair
.records
= recordContents
;
7916 pair
.signatures
= signatureContents
;
7917 denialMap
[std::make_pair(DNSName("example.org."), QType::NSEC
)] = pair
;
7919 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
7920 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7922 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7923 /* let's check that d.example.org. is not denied by this proof */
7924 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7927 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_1
) {
7931 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7933 vector
<DNSRecord
> records
;
7935 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7936 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7939 Wrap case 1 test case:
7940 z.example.org. -> b.example.org. denies the existence of a.example.org.
7942 addNSECRecordToLW(DNSName("z.example.org."), DNSName("b.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7943 recordContents
.push_back(records
.at(0).d_content
);
7944 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7945 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7948 ContentSigPair pair
;
7949 pair
.records
= recordContents
;
7950 pair
.signatures
= signatureContents
;
7952 denialMap
[std::make_pair(DNSName("z.example.org."), QType::NSEC
)] = pair
;
7954 dState denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
7955 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7957 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7958 /* let's check that d.example.org. is not denied by this proof */
7959 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7962 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_2
) {
7966 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7968 vector
<DNSRecord
> records
;
7970 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
7971 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
7974 Wrap case 2 test case:
7975 y.example.org. -> a.example.org. denies the existence of z.example.org.
7977 addNSECRecordToLW(DNSName("y.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
7978 recordContents
.push_back(records
.at(0).d_content
);
7979 addRRSIG(keys
, records
, DNSName("example.org."), 300);
7980 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
7983 ContentSigPair pair
;
7984 pair
.records
= recordContents
;
7985 pair
.signatures
= signatureContents
;
7987 denialMap
[std::make_pair(DNSName("y.example.org."), QType::NSEC
)] = pair
;
7989 dState denialState
= getDenial(denialMap
, DNSName("z.example.org."), QType::A
, false, false);
7990 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
7992 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
7993 /* let's check that d.example.org. is not denied by this proof */
7994 BOOST_CHECK_EQUAL(denialState
, NODATA
);
7997 BOOST_AUTO_TEST_CASE(test_nsec_denial_only_one_nsec
) {
8001 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8003 vector
<DNSRecord
> records
;
8005 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8006 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8009 Only one NSEC in the whole zone test case:
8010 a.example.org. -> a.example.org. denies the existence of b.example.org.
8012 addNSECRecordToLW(DNSName("a.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8013 recordContents
.push_back(records
.at(0).d_content
);
8014 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8015 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8018 ContentSigPair pair
;
8019 pair
.records
= recordContents
;
8020 pair
.signatures
= signatureContents
;
8022 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
8024 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
8025 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8027 denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
8028 /* let's check that d.example.org. is not denied by this proof */
8029 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8032 BOOST_AUTO_TEST_CASE(test_nsec_root_nxd_denial
) {
8036 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8038 vector
<DNSRecord
> records
;
8040 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8041 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8044 The RRSIG from "." denies the existence of anything between a. and c.,
8047 addNSECRecordToLW(DNSName("a."), DNSName("c."), { QType::NS
}, 600, records
);
8048 recordContents
.push_back(records
.at(0).d_content
);
8049 addRRSIG(keys
, records
, DNSName("."), 300);
8050 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8053 ContentSigPair pair
;
8054 pair
.records
= recordContents
;
8055 pair
.signatures
= signatureContents
;
8057 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8059 /* add wildcard denial */
8060 recordContents
.clear();
8061 signatureContents
.clear();
8062 addNSECRecordToLW(DNSName("."), DNSName("+"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8063 recordContents
.push_back(records
.at(0).d_content
);
8064 addRRSIG(keys
, records
, DNSName("."), 300);
8065 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8068 pair
.records
= recordContents
;
8069 pair
.signatures
= signatureContents
;
8070 denialMap
[std::make_pair(DNSName("."), QType::NSEC
)] = pair
;
8072 dState denialState
= getDenial(denialMap
, DNSName("b."), QType::A
, false, false);
8073 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8076 BOOST_AUTO_TEST_CASE(test_nsec_ancestor_nxqtype_denial
) {
8080 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8082 vector
<DNSRecord
> records
;
8084 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8085 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8088 The RRSIG from "." denies the existence of any type except NS at a.
8089 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8090 signer field that is shorter than the owner name of the NSEC RR) it can't
8091 be used to deny anything except the whole name or a DS.
8093 addNSECRecordToLW(DNSName("a."), DNSName("b."), { QType::NS
}, 600, records
);
8094 recordContents
.push_back(records
.at(0).d_content
);
8095 addRRSIG(keys
, records
, DNSName("."), 300);
8096 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8099 ContentSigPair pair
;
8100 pair
.records
= recordContents
;
8101 pair
.signatures
= signatureContents
;
8103 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8105 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8106 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8107 nonexistence of any RRs below that zone cut, which include all RRs at
8108 that (original) owner name other than DS RRs, and all RRs below that
8109 owner name regardless of type.
8112 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, false);
8113 /* no data means the qname/qtype is not denied, because an ancestor
8114 delegation NSEC can only deny the DS */
8115 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8117 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8118 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8121 BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial
) {
8125 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8127 vector
<DNSRecord
> records
;
8129 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8130 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8133 * RFC 5155 section 8.9:
8134 * If there is an NSEC3 RR present in the response that matches the
8135 * delegation name, then the validator MUST ensure that the NS bit is
8136 * set and that the DS bit is not set in the Type Bit Maps field of the
8140 The RRSIG from "." denies the existence of any type at a.
8141 NS should be set if it was proving an insecure delegation, let's check that
8142 we correctly detect that it's not.
8144 addNSECRecordToLW(DNSName("a."), DNSName("b."), { }, 600, records
);
8145 recordContents
.push_back(records
.at(0).d_content
);
8146 addRRSIG(keys
, records
, DNSName("."), 300);
8147 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8150 ContentSigPair pair
;
8151 pair
.records
= recordContents
;
8152 pair
.signatures
= signatureContents
;
8154 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8156 /* Insecure because the NS is not set, so while it does
8157 denies the DS, it can't prove an insecure delegation */
8158 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8159 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8162 BOOST_AUTO_TEST_CASE(test_nsec_nxqtype_cname
) {
8166 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8168 vector
<DNSRecord
> records
;
8170 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8171 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8173 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::CNAME
}, 600, records
);
8174 recordContents
.push_back(records
.at(0).d_content
);
8175 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8176 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8179 ContentSigPair pair
;
8180 pair
.records
= recordContents
;
8181 pair
.signatures
= signatureContents
;
8183 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8185 /* this NSEC is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8186 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, true, true);
8187 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8190 BOOST_AUTO_TEST_CASE(test_nsec3_nxqtype_cname
) {
8194 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8196 vector
<DNSRecord
> records
;
8198 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8199 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8201 addNSEC3UnhashedRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::CNAME
}, 600, records
);
8202 recordContents
.push_back(records
.at(0).d_content
);
8203 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8204 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8206 ContentSigPair pair
;
8207 pair
.records
= recordContents
;
8208 pair
.signatures
= signatureContents
;
8210 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8213 /* this NSEC3 is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8214 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, false, true);
8215 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8218 BOOST_AUTO_TEST_CASE(test_nsec_nxdomain_denial_missing_wildcard
) {
8222 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8224 vector
<DNSRecord
> records
;
8226 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8227 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8229 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("d.powerdns.com"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8230 recordContents
.push_back(records
.at(0).d_content
);
8231 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8232 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8235 ContentSigPair pair
;
8236 pair
.records
= recordContents
;
8237 pair
.signatures
= signatureContents
;
8239 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8241 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8242 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8245 BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard
) {
8249 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8251 vector
<DNSRecord
> records
;
8253 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8254 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8256 addNSEC3NarrowRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8257 recordContents
.push_back(records
.at(0).d_content
);
8258 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8259 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8261 ContentSigPair pair
;
8262 pair
.records
= recordContents
;
8263 pair
.signatures
= signatureContents
;
8265 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8267 /* Add NSEC3 for the closest encloser */
8268 recordContents
.clear();
8269 signatureContents
.clear();
8271 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8272 recordContents
.push_back(records
.at(0).d_content
);
8273 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8274 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8276 pair
.records
= recordContents
;
8277 pair
.signatures
= signatureContents
;
8278 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8280 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8281 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8284 BOOST_AUTO_TEST_CASE(test_nsec_ent_denial
) {
8288 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8290 vector
<DNSRecord
> records
;
8292 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8293 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8295 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::A
}, 600, records
);
8296 recordContents
.push_back(records
.at(0).d_content
);
8297 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8298 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8301 ContentSigPair pair
;
8302 pair
.records
= recordContents
;
8303 pair
.signatures
= signatureContents
;
8305 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8307 /* this NSEC is valid to prove a NXQTYPE at c.powerdns.com because it proves that
8309 dState denialState
= getDenial(denialMap
, DNSName("c.powerdns.com."), QType::AAAA
, true, true);
8310 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8312 /* this NSEC is not valid to prove a NXQTYPE at b.powerdns.com,
8313 it could prove a NXDOMAIN if it had an additional wildcard denial */
8314 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::AAAA
, true, true);
8315 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8317 /* this NSEC is not valid to prove a NXQTYPE for QType::A at a.c.powerdns.com either */
8318 denialState
= getDenial(denialMap
, DNSName("a.c.powerdns.com."), QType::A
, true, true);
8319 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8321 /* if we add the wildcard denial proof, we should get a NXDOMAIN proof for b.powerdns.com */
8322 recordContents
.clear();
8323 signatureContents
.clear();
8324 addNSECRecordToLW(DNSName(").powerdns.com."), DNSName("+.powerdns.com."), { }, 600, records
);
8325 recordContents
.push_back(records
.at(0).d_content
);
8326 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8327 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8329 pair
.records
= recordContents
;
8330 pair
.signatures
= signatureContents
;
8331 denialMap
[std::make_pair(DNSName(").powerdns.com."), QType::NSEC
)] = pair
;
8333 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, true, false);
8334 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8337 BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial
) {
8341 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8343 vector
<DNSRecord
> records
;
8345 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8346 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8349 The RRSIG from "." denies the existence of any type except NS at a.
8350 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8351 signer field that is shorter than the owner name of the NSEC RR) it can't
8352 be used to deny anything except the whole name or a DS.
8354 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::NS
}, 600, records
);
8355 recordContents
.push_back(records
.at(0).d_content
);
8356 addRRSIG(keys
, records
, DNSName("."), 300);
8357 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8359 ContentSigPair pair
;
8360 pair
.records
= recordContents
;
8361 pair
.signatures
= signatureContents
;
8363 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8366 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8367 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8368 nonexistence of any RRs below that zone cut, which include all RRs at
8369 that (original) owner name other than DS RRs, and all RRs below that
8370 owner name regardless of type.
8373 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8374 /* no data means the qname/qtype is not denied, because an ancestor
8375 delegation NSEC3 can only deny the DS */
8376 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8378 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8379 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8382 BOOST_AUTO_TEST_CASE(test_nsec3_denial_too_many_iterations
) {
8386 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8388 vector
<DNSRecord
> records
;
8390 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8391 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8393 /* adding a NSEC3 with more iterations that we support */
8394 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::AAAA
}, 600, records
, g_maxNSEC3Iterations
+ 100);
8395 recordContents
.push_back(records
.at(0).d_content
);
8396 addRRSIG(keys
, records
, DNSName("."), 300);
8397 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8399 ContentSigPair pair
;
8400 pair
.records
= recordContents
;
8401 pair
.signatures
= signatureContents
;
8403 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8406 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8407 /* since we refuse to compute more than g_maxNSEC3Iterations iterations, it should be Insecure */
8408 BOOST_CHECK_EQUAL(denialState
, INSECURE
);
8411 BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial
) {
8415 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8417 vector
<DNSRecord
> records
;
8419 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8420 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8423 * RFC 5155 section 8.9:
8424 * If there is an NSEC3 RR present in the response that matches the
8425 * delegation name, then the validator MUST ensure that the NS bit is
8426 * set and that the DS bit is not set in the Type Bit Maps field of the
8430 The RRSIG from "." denies the existence of any type at a.
8431 NS should be set if it was proving an insecure delegation, let's check that
8432 we correctly detect that it's not.
8434 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { }, 600, records
);
8435 recordContents
.push_back(records
.at(0).d_content
);
8436 addRRSIG(keys
, records
, DNSName("."), 300);
8437 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8439 ContentSigPair pair
;
8440 pair
.records
= recordContents
;
8441 pair
.signatures
= signatureContents
;
8443 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8446 /* Insecure because the NS is not set, so while it does
8447 denies the DS, it can't prove an insecure delegation */
8448 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8449 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8452 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_negcache_validity
) {
8453 std::unique_ptr
<SyncRes
> sr
;
8456 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8459 const DNSName
target("com.");
8462 auto luaconfsCopy
= g_luaconfs
.getCopy();
8463 luaconfsCopy
.dsAnchors
.clear();
8464 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8465 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8466 g_luaconfs
.setState(luaconfsCopy
);
8468 size_t queriesCount
= 0;
8470 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
) {
8473 DNSName auth
= domain
;
8476 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8477 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8480 setLWResult(res
, RCode::NoError
, true, false, true);
8481 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8482 addRRSIG(keys
, res
->d_records
, domain
, 300);
8483 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
8484 addRRSIG(keys
, res
->d_records
, domain
, 1);
8491 const time_t now
= time(nullptr);
8492 vector
<DNSRecord
> ret
;
8493 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8494 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8495 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8496 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8497 BOOST_CHECK_EQUAL(queriesCount
, 4);
8499 /* check that the entry has not been negatively cached for longer than the RRSIG validity */
8500 NegCache::NegCacheEntry ne
;
8501 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
8502 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
8503 BOOST_CHECK_EQUAL(ne
.d_ttd
, now
+ 1);
8504 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
8505 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
8506 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
8507 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
8508 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
8510 /* again, to test the cache */
8512 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8513 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8514 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8515 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8516 BOOST_CHECK_EQUAL(queriesCount
, 4);
8519 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_cache_validity
) {
8520 std::unique_ptr
<SyncRes
> sr
;
8523 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8526 const DNSName
target("com.");
8527 const ComboAddress
targetAddr("192.0.2.42");
8530 auto luaconfsCopy
= g_luaconfs
.getCopy();
8531 luaconfsCopy
.dsAnchors
.clear();
8532 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8533 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8534 g_luaconfs
.setState(luaconfsCopy
);
8536 size_t queriesCount
= 0;
8538 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
) {
8541 DNSName auth
= domain
;
8544 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8545 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8548 setLWResult(res
, RCode::NoError
, true, false, true);
8549 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
8550 addRRSIG(keys
, res
->d_records
, domain
, 1);
8557 const time_t now
= time(nullptr);
8558 vector
<DNSRecord
> ret
;
8559 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8560 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8561 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8562 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8563 BOOST_CHECK_EQUAL(queriesCount
, 4);
8565 /* check that the entry has not been cached for longer than the RRSIG validity */
8566 const ComboAddress who
;
8567 vector
<DNSRecord
> cached
;
8568 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
8569 BOOST_REQUIRE_EQUAL(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
, &signatures
), 1);
8570 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
8571 BOOST_REQUIRE_EQUAL(signatures
.size(), 1);
8572 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), 1);
8574 /* again, to test the cache */
8576 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8577 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8578 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8579 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8580 BOOST_CHECK_EQUAL(queriesCount
, 4);
8583 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_secure
) {
8585 Validation is optional, and the first query does not ask for it,
8586 so the answer is cached as Indeterminate.
8587 The second query asks for validation, answer should be marked as
8590 std::unique_ptr
<SyncRes
> sr
;
8593 setDNSSECValidation(sr
, DNSSECMode::Process
);
8596 const DNSName
target("com.");
8599 auto luaconfsCopy
= g_luaconfs
.getCopy();
8600 luaconfsCopy
.dsAnchors
.clear();
8601 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8602 g_luaconfs
.setState(luaconfsCopy
);
8604 size_t queriesCount
= 0;
8606 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
) {
8609 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8610 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8613 if (domain
== target
&& type
== QType::A
) {
8614 setLWResult(res
, 0, true, false, true);
8615 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8616 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8624 vector
<DNSRecord
> ret
;
8625 /* first query does not require validation */
8626 sr
->setDNSSECValidationRequested(false);
8627 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8628 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8629 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8630 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8631 for (const auto& record
: ret
) {
8632 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8634 BOOST_CHECK_EQUAL(queriesCount
, 1);
8638 /* second one _does_ require validation */
8639 sr
->setDNSSECValidationRequested(true);
8640 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8641 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8642 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8643 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8644 for (const auto& record
: ret
) {
8645 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8647 BOOST_CHECK_EQUAL(queriesCount
, 3);
8650 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_insecure
) {
8652 Validation is optional, and the first query does not ask for it,
8653 so the answer is cached as Indeterminate.
8654 The second query asks for validation, answer should be marked as
8657 std::unique_ptr
<SyncRes
> sr
;
8660 setDNSSECValidation(sr
, DNSSECMode::Process
);
8663 const DNSName
target("com.");
8666 auto luaconfsCopy
= g_luaconfs
.getCopy();
8667 luaconfsCopy
.dsAnchors
.clear();
8668 g_luaconfs
.setState(luaconfsCopy
);
8670 size_t queriesCount
= 0;
8672 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
) {
8675 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8676 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8679 if (domain
== target
&& type
== QType::A
) {
8680 setLWResult(res
, 0, true, false, true);
8681 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8689 vector
<DNSRecord
> ret
;
8690 /* first query does not require validation */
8691 sr
->setDNSSECValidationRequested(false);
8692 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8693 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8694 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8695 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8696 for (const auto& record
: ret
) {
8697 BOOST_CHECK(record
.d_type
== QType::A
);
8699 BOOST_CHECK_EQUAL(queriesCount
, 1);
8703 /* second one _does_ require validation */
8704 sr
->setDNSSECValidationRequested(true);
8705 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8706 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8707 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8708 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8709 for (const auto& record
: ret
) {
8710 BOOST_CHECK(record
.d_type
== QType::A
);
8712 BOOST_CHECK_EQUAL(queriesCount
, 1);
8715 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_bogus
) {
8717 Validation is optional, and the first query does not ask for it,
8718 so the answer is cached as Indeterminate.
8719 The second query asks for validation, answer should be marked as
8722 std::unique_ptr
<SyncRes
> sr
;
8725 setDNSSECValidation(sr
, DNSSECMode::Process
);
8728 const DNSName
target("com.");
8731 auto luaconfsCopy
= g_luaconfs
.getCopy();
8732 luaconfsCopy
.dsAnchors
.clear();
8733 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8734 g_luaconfs
.setState(luaconfsCopy
);
8736 size_t queriesCount
= 0;
8738 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
) {
8741 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8742 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8745 if (domain
== target
&& type
== QType::A
) {
8746 setLWResult(res
, 0, true, false, true);
8747 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8756 vector
<DNSRecord
> ret
;
8757 /* first query does not require validation */
8758 sr
->setDNSSECValidationRequested(false);
8759 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8760 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8761 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8762 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8763 for (const auto& record
: ret
) {
8764 BOOST_CHECK(record
.d_type
== QType::A
);
8766 BOOST_CHECK_EQUAL(queriesCount
, 1);
8770 /* second one _does_ require validation */
8771 sr
->setDNSSECValidationRequested(true);
8772 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8773 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8774 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8775 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8776 for (const auto& record
: ret
) {
8777 BOOST_CHECK(record
.d_type
== QType::A
);
8779 BOOST_CHECK_EQUAL(queriesCount
, 3);
8782 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_secure
) {
8784 Validation is optional, and the first query does not ask for it,
8785 so the answer is cached as Indeterminate.
8786 The second query asks for validation, answer should be marked as
8789 std::unique_ptr
<SyncRes
> sr
;
8792 setDNSSECValidation(sr
, DNSSECMode::Process
);
8795 const DNSName
target("com.");
8796 const DNSName
cnameTarget("cname-com.");
8799 auto luaconfsCopy
= g_luaconfs
.getCopy();
8800 luaconfsCopy
.dsAnchors
.clear();
8801 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8802 g_luaconfs
.setState(luaconfsCopy
);
8804 size_t queriesCount
= 0;
8806 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
) {
8809 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8810 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8813 if (domain
== target
&& type
== QType::A
) {
8814 setLWResult(res
, 0, true, false, true);
8815 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
8816 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8817 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8818 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8820 } else if (domain
== cnameTarget
&& type
== QType::A
) {
8821 setLWResult(res
, 0, true, false, true);
8822 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8823 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8831 vector
<DNSRecord
> ret
;
8832 /* first query does not require validation */
8833 sr
->setDNSSECValidationRequested(false);
8834 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8835 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8836 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8837 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8838 for (const auto& record
: ret
) {
8839 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8841 BOOST_CHECK_EQUAL(queriesCount
, 2);
8845 /* second one _does_ require validation */
8846 sr
->setDNSSECValidationRequested(true);
8847 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8848 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8849 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8850 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8851 for (const auto& record
: ret
) {
8852 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8854 BOOST_CHECK_EQUAL(queriesCount
, 5);
8857 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_insecure
) {
8859 Validation is optional, and the first query does not ask for it,
8860 so the answer is cached as Indeterminate.
8861 The second query asks for validation, answer should be marked as
8864 std::unique_ptr
<SyncRes
> sr
;
8867 setDNSSECValidation(sr
, DNSSECMode::Process
);
8870 const DNSName
target("com.");
8871 const DNSName
cnameTarget("cname-com.");
8874 auto luaconfsCopy
= g_luaconfs
.getCopy();
8875 luaconfsCopy
.dsAnchors
.clear();
8876 g_luaconfs
.setState(luaconfsCopy
);
8878 size_t queriesCount
= 0;
8880 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
) {
8883 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8884 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8887 if (domain
== target
&& type
== QType::A
) {
8888 setLWResult(res
, 0, true, false, true);
8889 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
8890 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8892 } else if (domain
== cnameTarget
&& type
== QType::A
) {
8893 setLWResult(res
, 0, true, false, true);
8894 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8902 vector
<DNSRecord
> ret
;
8903 /* first query does not require validation */
8904 sr
->setDNSSECValidationRequested(false);
8905 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8906 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8907 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8908 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8909 for (const auto& record
: ret
) {
8910 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8912 BOOST_CHECK_EQUAL(queriesCount
, 2);
8916 /* second one _does_ require validation */
8917 sr
->setDNSSECValidationRequested(true);
8918 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8919 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8920 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8921 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8922 for (const auto& record
: ret
) {
8923 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8925 BOOST_CHECK_EQUAL(queriesCount
, 2);
8928 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_bogus
) {
8930 Validation is optional, and the first query does not ask for it,
8931 so the answer is cached as Indeterminate.
8932 The second query asks for validation, answer should be marked as
8935 std::unique_ptr
<SyncRes
> sr
;
8938 setDNSSECValidation(sr
, DNSSECMode::Process
);
8941 const DNSName
target("com.");
8942 const DNSName
cnameTarget("cname-com.");
8945 auto luaconfsCopy
= g_luaconfs
.getCopy();
8946 luaconfsCopy
.dsAnchors
.clear();
8947 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8948 g_luaconfs
.setState(luaconfsCopy
);
8950 size_t queriesCount
= 0;
8952 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
) {
8955 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8956 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8959 if (domain
== target
&& type
== QType::A
) {
8960 setLWResult(res
, 0, true, false, true);
8961 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
8962 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8965 } else if (domain
== cnameTarget
&& type
== QType::A
) {
8966 setLWResult(res
, 0, true, false, true);
8967 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
8976 vector
<DNSRecord
> ret
;
8977 /* first query does not require validation */
8978 sr
->setDNSSECValidationRequested(false);
8979 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8980 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8981 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8982 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8983 for (const auto& record
: ret
) {
8984 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8986 BOOST_CHECK_EQUAL(queriesCount
, 2);
8990 /* second one _does_ require validation */
8991 sr
->setDNSSECValidationRequested(true);
8992 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8993 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8994 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8995 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8996 for (const auto& record
: ret
) {
8997 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
8999 BOOST_CHECK_EQUAL(queriesCount
, 5);
9002 BOOST_AUTO_TEST_CASE(test_dnssec_validation_additional_without_rrsig
) {
9004 We get a record from a secure zone in the additional section, without
9005 the corresponding RRSIG. The record should not be marked as authoritative
9006 and should be correctly validated.
9008 std::unique_ptr
<SyncRes
> sr
;
9011 setDNSSECValidation(sr
, DNSSECMode::Process
);
9014 const DNSName
target("com.");
9015 const DNSName
addTarget("nsX.com.");
9018 auto luaconfsCopy
= g_luaconfs
.getCopy();
9019 luaconfsCopy
.dsAnchors
.clear();
9020 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9021 g_luaconfs
.setState(luaconfsCopy
);
9023 size_t queriesCount
= 0;
9025 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
) {
9028 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9029 if (domain
== addTarget
) {
9030 DNSName
auth(domain
);
9031 /* no DS for com, auth will be . */
9033 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, false);
9035 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9038 if (domain
== target
&& type
== QType::A
) {
9039 setLWResult(res
, 0, true, false, true);
9040 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
9041 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9042 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42", DNSResourceRecord::ADDITIONAL
);
9043 /* no RRSIG for the additional record */
9045 } else if (domain
== addTarget
&& type
== QType::A
) {
9046 setLWResult(res
, 0, true, false, true);
9047 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42");
9048 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9056 vector
<DNSRecord
> ret
;
9057 /* first query for target/A, will pick up the additional record as non-auth / unvalidated */
9058 sr
->setDNSSECValidationRequested(false);
9059 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9060 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9061 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9062 BOOST_CHECK_EQUAL(ret
.size(), 2);
9063 for (const auto& record
: ret
) {
9064 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9066 BOOST_CHECK_EQUAL(queriesCount
, 1);
9069 /* ask for the additional record directly, we should not use
9070 the non-auth one and issue a new query, properly validated */
9071 sr
->setDNSSECValidationRequested(true);
9072 res
= sr
->beginResolve(addTarget
, QType(QType::A
), QClass::IN
, ret
);
9073 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9074 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9075 BOOST_CHECK_EQUAL(ret
.size(), 2);
9076 for (const auto& record
: ret
) {
9077 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9079 BOOST_CHECK_EQUAL(queriesCount
, 5);
9082 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure
) {
9084 Validation is optional, and the first query does not ask for it,
9085 so the answer is negatively cached as Indeterminate.
9086 The second query asks for validation, answer should be marked as
9089 std::unique_ptr
<SyncRes
> sr
;
9092 setDNSSECValidation(sr
, DNSSECMode::Process
);
9095 const DNSName
target("com.");
9098 auto luaconfsCopy
= g_luaconfs
.getCopy();
9099 luaconfsCopy
.dsAnchors
.clear();
9100 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9101 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9102 g_luaconfs
.setState(luaconfsCopy
);
9104 size_t queriesCount
= 0;
9106 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
) {
9109 DNSName auth
= domain
;
9112 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9113 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9116 setLWResult(res
, RCode::NoError
, true, false, true);
9117 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9118 addRRSIG(keys
, res
->d_records
, domain
, 300);
9119 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
9120 addRRSIG(keys
, res
->d_records
, domain
, 1);
9127 vector
<DNSRecord
> ret
;
9128 /* first query does not require validation */
9129 sr
->setDNSSECValidationRequested(false);
9130 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9131 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9132 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9133 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9134 BOOST_CHECK_EQUAL(queriesCount
, 1);
9135 /* check that the entry has not been negatively cached */
9136 NegCache::NegCacheEntry ne
;
9137 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9138 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9139 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9140 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9141 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9142 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9143 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9146 /* second one _does_ require validation */
9147 sr
->setDNSSECValidationRequested(true);
9148 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9149 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9150 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9151 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9152 BOOST_CHECK_EQUAL(queriesCount
, 4);
9153 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9154 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9155 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
9156 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9157 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9158 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9159 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9162 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure_ds
) {
9164 Validation is optional, and the first query does not ask for it,
9165 so the answer is negatively cached as Indeterminate.
9166 The second query asks for validation, answer should be marked as
9168 The difference with test_dnssec_validation_from_negcache_secure is
9169 that have one more level here, so we are going to look for the proof
9170 that the DS does not exist for the last level. Since there is no cut,
9171 we should accept the fact that the NSEC denies DS and NS both.
9173 std::unique_ptr
<SyncRes
> sr
;
9176 setDNSSECValidation(sr
, DNSSECMode::Process
);
9179 const DNSName
target("www.com.");
9182 auto luaconfsCopy
= g_luaconfs
.getCopy();
9183 luaconfsCopy
.dsAnchors
.clear();
9184 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9185 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9186 g_luaconfs
.setState(luaconfsCopy
);
9188 size_t queriesCount
= 0;
9190 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
) {
9193 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9194 if (domain
== target
) {
9195 /* there is no cut */
9196 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9198 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
9204 vector
<DNSRecord
> ret
;
9205 /* first query does not require validation */
9206 sr
->setDNSSECValidationRequested(false);
9207 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9208 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9209 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9210 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9211 BOOST_CHECK_EQUAL(queriesCount
, 1);
9214 /* second one _does_ require validation */
9215 sr
->setDNSSECValidationRequested(true);
9216 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9217 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9218 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9219 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9220 BOOST_CHECK_EQUAL(queriesCount
, 4);
9223 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_insecure
) {
9225 Validation is optional, and the first query does not ask for it,
9226 so the answer is negatively cached as Indeterminate.
9227 The second query asks for validation, answer should be marked as
9230 std::unique_ptr
<SyncRes
> sr
;
9233 setDNSSECValidation(sr
, DNSSECMode::Process
);
9236 const DNSName
target("com.");
9239 auto luaconfsCopy
= g_luaconfs
.getCopy();
9240 luaconfsCopy
.dsAnchors
.clear();
9241 g_luaconfs
.setState(luaconfsCopy
);
9243 size_t queriesCount
= 0;
9245 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
) {
9248 DNSName auth
= domain
;
9251 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9252 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9255 setLWResult(res
, RCode::NoError
, true, false, true);
9256 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9263 vector
<DNSRecord
> ret
;
9264 /* first query does not require validation */
9265 sr
->setDNSSECValidationRequested(false);
9266 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9267 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9268 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9269 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9270 BOOST_CHECK_EQUAL(queriesCount
, 1);
9271 /* check that the entry has not been negatively cached */
9272 NegCache::NegCacheEntry ne
;
9273 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9274 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9275 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9276 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9277 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9278 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9279 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9282 /* second one _does_ require validation */
9283 sr
->setDNSSECValidationRequested(true);
9284 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9285 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9286 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9287 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9288 BOOST_CHECK_EQUAL(queriesCount
, 1);
9289 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9290 BOOST_CHECK_EQUAL(ne
.d_validationState
, Insecure
);
9291 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9292 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9293 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9294 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9297 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_bogus
) {
9299 Validation is optional, and the first query does not ask for it,
9300 so the answer is negatively cached as Indeterminate.
9301 The second query asks for validation, answer should be marked as
9304 std::unique_ptr
<SyncRes
> sr
;
9307 setDNSSECValidation(sr
, DNSSECMode::Process
);
9310 const DNSName
target("com.");
9313 auto luaconfsCopy
= g_luaconfs
.getCopy();
9314 luaconfsCopy
.dsAnchors
.clear();
9315 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9316 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9317 g_luaconfs
.setState(luaconfsCopy
);
9319 size_t queriesCount
= 0;
9321 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
) {
9324 DNSName auth
= domain
;
9327 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9328 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9331 setLWResult(res
, RCode::NoError
, true, false, true);
9332 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9333 addRRSIG(keys
, res
->d_records
, domain
, 300);
9341 vector
<DNSRecord
> ret
;
9342 /* first query does not require validation */
9343 sr
->setDNSSECValidationRequested(false);
9344 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9345 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9346 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9347 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9348 BOOST_CHECK_EQUAL(queriesCount
, 1);
9349 NegCache::NegCacheEntry ne
;
9350 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9351 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9352 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9353 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9354 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9355 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9356 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9359 /* second one _does_ require validation */
9360 sr
->setDNSSECValidationRequested(true);
9361 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9362 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9363 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9364 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9365 BOOST_CHECK_EQUAL(queriesCount
, 4);
9366 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9367 BOOST_CHECK_EQUAL(ne
.d_validationState
, Bogus
);
9368 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9369 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9370 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9371 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9374 BOOST_AUTO_TEST_CASE(test_lowercase_outgoing
) {
9375 g_lowercaseOutgoing
= true;
9376 std::unique_ptr
<SyncRes
> sr
;
9381 vector
<DNSName
> sentOutQnames
;
9383 const DNSName
target("WWW.POWERDNS.COM");
9384 const DNSName
cname("WWW.PowerDNS.org");
9386 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
) {
9388 sentOutQnames
.push_back(domain
);
9390 if (isRootServer(ip
)) {
9391 if (domain
== target
) {
9392 setLWResult(res
, 0, false, false, true);
9393 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
9394 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
9397 if (domain
== cname
) {
9398 setLWResult(res
, 0, false, false, true);
9399 addRecordToLW(res
, "powerdns.org.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
9400 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
9403 } else if (ip
== ComboAddress("192.0.2.1:53")) {
9404 if (domain
== target
) {
9405 setLWResult(res
, 0, true, false, false);
9406 addRecordToLW(res
, domain
, QType::CNAME
, cname
.toString());
9409 } else if (ip
== ComboAddress("192.0.2.2:53")) {
9410 if (domain
== cname
) {
9411 setLWResult(res
, 0, true, false, false);
9412 addRecordToLW(res
, domain
, QType::A
, "127.0.0.1");
9419 vector
<DNSRecord
> ret
;
9420 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9422 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9424 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9425 BOOST_CHECK_EQUAL(ret
[0].d_content
->getZoneRepresentation(), cname
.toString());
9427 BOOST_REQUIRE_EQUAL(sentOutQnames
.size(), 4);
9428 BOOST_CHECK_EQUAL(sentOutQnames
[0].toString(), target
.makeLowerCase().toString());
9429 BOOST_CHECK_EQUAL(sentOutQnames
[1].toString(), target
.makeLowerCase().toString());
9430 BOOST_CHECK_EQUAL(sentOutQnames
[2].toString(), cname
.makeLowerCase().toString());
9431 BOOST_CHECK_EQUAL(sentOutQnames
[3].toString(), cname
.makeLowerCase().toString());
9433 g_lowercaseOutgoing
= false;
9436 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo
) {
9437 std::unique_ptr
<SyncRes
> sr
;
9440 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9443 const DNSName
target("com.");
9444 testkeysset_t keys
, keys2
;
9446 auto luaconfsCopy
= g_luaconfs
.getCopy();
9447 luaconfsCopy
.dsAnchors
.clear();
9448 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9449 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9450 g_luaconfs
.setState(luaconfsCopy
);
9452 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9453 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9454 // But add the existing root key otherwise no RRSIG can be created
9455 auto rootkey
= keys
.find(g_rootdnsname
);
9456 keys2
.insert(*rootkey
);
9458 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
) {
9459 DNSName auth
= domain
;
9461 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9462 if (domain
== target
) {
9463 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9467 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9473 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9474 BOOST_CHECK_EQUAL(state
, Secure
);
9475 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9476 for (const auto& i
: ds
) {
9477 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9481 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_all_sha
) {
9482 std::unique_ptr
<SyncRes
> sr
;
9485 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9488 const DNSName
target("com.");
9489 testkeysset_t keys
, keys2
, keys3
;
9491 auto luaconfsCopy
= g_luaconfs
.getCopy();
9492 luaconfsCopy
.dsAnchors
.clear();
9493 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9494 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9495 g_luaconfs
.setState(luaconfsCopy
);
9497 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9498 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9499 // But add the existing root key otherwise no RRSIG can be created
9500 auto rootkey
= keys
.find(g_rootdnsname
);
9501 keys2
.insert(*rootkey
);
9503 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys3
);
9504 // But add the existing root key otherwise no RRSIG can be created
9505 keys3
.insert(*rootkey
);
9507 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
) {
9508 DNSName auth
= domain
;
9510 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9511 if (domain
== target
) {
9512 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9515 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9519 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9525 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9526 BOOST_CHECK_EQUAL(state
, Secure
);
9527 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9528 for (const auto& i
: ds
) {
9529 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
9533 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_two_highest
) {
9534 std::unique_ptr
<SyncRes
> sr
;
9537 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9540 const DNSName
target("com.");
9541 testkeysset_t keys
, keys2
, keys3
;
9543 auto luaconfsCopy
= g_luaconfs
.getCopy();
9544 luaconfsCopy
.dsAnchors
.clear();
9545 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9546 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9547 g_luaconfs
.setState(luaconfsCopy
);
9549 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9550 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys2
);
9551 // But add the existing root key otherwise no RRSIG can be created
9552 auto rootkey
= keys
.find(g_rootdnsname
);
9553 keys2
.insert(*rootkey
);
9555 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys3
);
9556 // But add the existing root key otherwise no RRSIG can be created
9557 keys3
.insert(*rootkey
);
9559 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
) {
9560 DNSName auth
= domain
;
9562 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9563 if (domain
== target
) {
9564 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9567 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9571 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9577 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9578 BOOST_CHECK_EQUAL(state
, Secure
);
9579 BOOST_REQUIRE_EQUAL(ds
.size(), 2);
9580 for (const auto& i
: ds
) {
9581 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9586 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha384_over_gost
) {
9587 std::unique_ptr
<SyncRes
> sr
;
9590 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9593 const DNSName
target("com.");
9594 testkeysset_t keys
, keys2
;
9596 auto luaconfsCopy
= g_luaconfs
.getCopy();
9597 luaconfsCopy
.dsAnchors
.clear();
9598 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9599 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys
);
9600 g_luaconfs
.setState(luaconfsCopy
);
9602 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9603 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9604 // But add the existing root key otherwise no RRSIG can be created
9605 auto rootkey
= keys
.find(g_rootdnsname
);
9606 keys2
.insert(*rootkey
);
9608 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
) {
9609 DNSName auth
= domain
;
9611 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9612 if (domain
== target
) {
9613 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9617 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9623 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9624 BOOST_CHECK_EQUAL(state
, Secure
);
9625 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9626 for (const auto& i
: ds
) {
9627 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
9631 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha256_over_gost
) {
9632 std::unique_ptr
<SyncRes
> sr
;
9635 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9638 const DNSName
target("com.");
9639 testkeysset_t keys
, keys2
;
9641 auto luaconfsCopy
= g_luaconfs
.getCopy();
9642 luaconfsCopy
.dsAnchors
.clear();
9643 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9644 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9645 g_luaconfs
.setState(luaconfsCopy
);
9647 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9648 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9649 // But add the existing root key otherwise no RRSIG can be created
9650 auto rootkey
= keys
.find(g_rootdnsname
);
9651 keys2
.insert(*rootkey
);
9653 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
) {
9654 DNSName auth
= domain
;
9656 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9657 if (domain
== target
) {
9658 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9662 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9668 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9669 BOOST_CHECK_EQUAL(state
, Secure
);
9670 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9671 for (const auto& i
: ds
) {
9672 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9676 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_gost_over_sha1
) {
9677 std::unique_ptr
<SyncRes
> sr
;
9680 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9683 const DNSName
target("com.");
9684 testkeysset_t keys
, keys2
;
9686 auto luaconfsCopy
= g_luaconfs
.getCopy();
9687 luaconfsCopy
.dsAnchors
.clear();
9688 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9689 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys
);
9690 g_luaconfs
.setState(luaconfsCopy
);
9692 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9693 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9694 // But add the existing root key otherwise no RRSIG can be created
9695 auto rootkey
= keys
.find(g_rootdnsname
);
9696 keys2
.insert(*rootkey
);
9698 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
) {
9699 DNSName auth
= domain
;
9701 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9702 if (domain
== target
) {
9703 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9707 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9713 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9714 BOOST_CHECK_EQUAL(state
, Secure
);
9715 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9716 for (const auto& i
: ds
) {
9717 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::GOST
);
9720 #endif // HAVE_BOTAN110
9723 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
9725 - check out of band support
9731 BOOST_AUTO_TEST_SUITE_END()