1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3 #include <boost/test/unit_test.hpp>
6 #include "arguments.hh"
8 #include "dnssecinfra.hh"
9 #include "dnsseckeeper.hh"
10 #include "lua-recursor4.hh"
11 #include "namespaces.hh"
12 #include "rec-lua-conf.hh"
13 #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
) const
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
, bool* chained
)
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
) {
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
=std::dynamic_pointer_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
=std::dynamic_pointer_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
, bool* chained
) {
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
, bool* chained
) {
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
, bool* chained
) {
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
, bool* chained
) {
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
, bool* chained
) {
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_edns_formerr_but_edns_enabled
) {
651 std::unique_ptr
<SyncRes
> sr
;
654 /* in this test, the auth answers with FormErr to an EDNS-enabled
655 query, but the response does contain EDNS so we should not mark
656 it as EDNS ignorant or intolerant.
658 size_t queriesWithEDNS
= 0;
659 size_t queriesWithoutEDNS
= 0;
660 std::set
<ComboAddress
> usedServers
;
662 sr
->setAsyncCallback([&queriesWithEDNS
, &queriesWithoutEDNS
, &usedServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
664 if (EDNS0Level
> 0) {
668 queriesWithoutEDNS
++;
670 usedServers
.insert(ip
);
672 if (type
== QType::DNAME
) {
673 setLWResult(res
, RCode::FormErr
);
674 if (EDNS0Level
> 0) {
675 res
->d_haveEDNS
= true;
685 vector
<DNSRecord
> ret
;
686 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::DNAME
), QClass::IN
, ret
);
687 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
688 BOOST_CHECK_EQUAL(ret
.size(), 0);
689 BOOST_CHECK_EQUAL(queriesWithEDNS
, 26);
690 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 0);
691 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 26);
692 BOOST_CHECK_EQUAL(usedServers
.size(), 26);
693 for (const auto& server
: usedServers
) {
694 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
698 BOOST_AUTO_TEST_CASE(test_meta_types
) {
699 std::unique_ptr
<SyncRes
> sr
;
702 static const std::set
<uint16_t> invalidTypes
= { 128, QType::AXFR
, QType::IXFR
, QType::RRSIG
, QType::NSEC3
, QType::OPT
, QType::TSIG
, QType::TKEY
, QType::MAILA
, QType::MAILB
, 65535 };
704 for (const auto qtype
: invalidTypes
) {
705 size_t queriesCount
= 0;
707 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
, bool* chained
) {
715 vector
<DNSRecord
> ret
;
716 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(qtype
), QClass::IN
, ret
);
717 BOOST_CHECK_EQUAL(res
, -1);
718 BOOST_CHECK_EQUAL(ret
.size(), 0);
719 BOOST_CHECK_EQUAL(queriesCount
, 0);
723 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
) {
724 std::unique_ptr
<SyncRes
> sr
;
727 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
, bool* chained
) {
729 setLWResult(res
, 0, false, true, false);
732 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
733 setLWResult(res
, 0, true, false, false);
734 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
743 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
744 vector
<DNSRecord
> ret
;
745 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
746 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
749 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
) {
750 std::unique_ptr
<SyncRes
> sr
;
753 size_t tcpQueriesCount
= 0;
755 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
, bool* chained
) {
757 setLWResult(res
, 0, true, true, false);
761 /* first TCP query is answered with a TC response */
763 if (tcpQueriesCount
== 1) {
764 setLWResult(res
, 0, true, true, false);
767 setLWResult(res
, 0, true, false, false);
770 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
776 vector
<DNSRecord
> ret
;
777 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
778 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
779 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2);
782 BOOST_AUTO_TEST_CASE(test_all_nss_down
) {
783 std::unique_ptr
<SyncRes
> sr
;
785 std::set
<ComboAddress
> downServers
;
789 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
, bool* chained
) {
791 if (isRootServer(ip
)) {
792 setLWResult(res
, 0, false, false, true);
793 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
794 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
795 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
798 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
799 setLWResult(res
, 0, false, false, true);
800 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
801 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
802 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
803 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
804 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
805 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
809 downServers
.insert(ip
);
814 DNSName
target("powerdns.com.");
816 vector
<DNSRecord
> ret
;
817 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
818 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
819 BOOST_CHECK_EQUAL(ret
.size(), 0);
820 BOOST_CHECK_EQUAL(downServers
.size(), 4);
822 for (const auto& server
: downServers
) {
823 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
824 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
828 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
) {
829 std::unique_ptr
<SyncRes
> sr
;
831 std::set
<ComboAddress
> downServers
;
835 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
, bool* chained
) {
837 if (isRootServer(ip
)) {
838 setLWResult(res
, 0, false, false, true);
839 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
840 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
841 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
844 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
845 setLWResult(res
, 0, false, false, true);
846 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
847 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
848 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
849 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
850 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
851 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
855 downServers
.insert(ip
);
860 /* exact same test than the previous one, except instead of a time out we fake a network error */
861 DNSName
target("powerdns.com.");
863 vector
<DNSRecord
> ret
;
864 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
865 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
866 BOOST_CHECK_EQUAL(ret
.size(), 0);
867 BOOST_CHECK_EQUAL(downServers
.size(), 4);
869 for (const auto& server
: downServers
) {
870 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
871 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
875 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
) {
876 std::unique_ptr
<SyncRes
> sr
;
881 DNSName
target("www.powerdns.com.");
883 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
, bool* chained
) {
885 if (isRootServer(ip
)) {
886 setLWResult(res
, 0, false, false, true);
887 if (domain
== target
) {
888 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
889 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
890 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
891 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
893 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
894 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
895 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
896 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
897 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
901 else if (ip
== ComboAddress("192.0.2.3:53")) {
902 setLWResult(res
, 0, true, false, true);
903 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
904 if (type
== QType::A
) {
905 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
907 else if (type
== QType::AAAA
) {
908 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
911 else if (domain
== target
) {
912 if (type
== QType::A
) {
913 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
915 else if (type
== QType::AAAA
) {
916 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
924 vector
<DNSRecord
> ret
;
925 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
926 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
927 BOOST_CHECK_EQUAL(ret
.size(), 1);
930 BOOST_AUTO_TEST_CASE(test_os_limit_errors
) {
931 std::unique_ptr
<SyncRes
> sr
;
933 std::set
<ComboAddress
> downServers
;
937 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
, bool* chained
) {
939 if (isRootServer(ip
)) {
940 setLWResult(res
, 0, false, false, true);
941 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
942 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
943 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
946 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
947 setLWResult(res
, 0, false, false, true);
948 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
949 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
950 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
951 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
952 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
953 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
957 if (downServers
.size() < 3) {
958 /* only the last one will answer */
959 downServers
.insert(ip
);
963 setLWResult(res
, 0, true, false, true);
964 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
970 DNSName
target("powerdns.com.");
972 vector
<DNSRecord
> ret
;
973 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
974 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
975 BOOST_CHECK_EQUAL(ret
.size(), 1);
976 BOOST_CHECK_EQUAL(downServers
.size(), 3);
978 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
979 for (const auto& server
: downServers
) {
980 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
981 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
985 BOOST_AUTO_TEST_CASE(test_glued_referral
) {
986 std::unique_ptr
<SyncRes
> sr
;
991 const DNSName
target("powerdns.com.");
993 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
, bool* chained
) {
994 /* this will cause issue with qname minimization if we ever implement it */
995 if (domain
!= target
) {
999 if (isRootServer(ip
)) {
1000 setLWResult(res
, 0, false, false, true);
1001 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1002 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1003 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1006 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
1007 setLWResult(res
, 0, false, false, true);
1008 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1009 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1010 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
1011 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
1012 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
1013 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
1016 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")) {
1017 setLWResult(res
, 0, true, false, true);
1018 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1026 vector
<DNSRecord
> ret
;
1027 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1028 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1029 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1030 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1031 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1034 BOOST_AUTO_TEST_CASE(test_glueless_referral
) {
1035 std::unique_ptr
<SyncRes
> sr
;
1040 const DNSName
target("powerdns.com.");
1042 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
, bool* chained
) {
1044 if (isRootServer(ip
)) {
1045 setLWResult(res
, 0, false, false, true);
1047 if (domain
.isPartOf(DNSName("com."))) {
1048 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1049 } else if (domain
.isPartOf(DNSName("org."))) {
1050 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1053 setLWResult(res
, RCode::NXDomain
, false, false, true);
1057 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1058 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1061 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
1062 if (domain
== target
) {
1063 setLWResult(res
, 0, false, false, true);
1064 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1065 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1068 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
1069 setLWResult(res
, 0, true, false, true);
1070 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
1071 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1074 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1075 setLWResult(res
, 0, true, false, true);
1076 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1077 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1081 setLWResult(res
, RCode::NXDomain
, false, false, true);
1084 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")) {
1085 setLWResult(res
, 0, true, false, true);
1086 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1094 vector
<DNSRecord
> ret
;
1095 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1096 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1097 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1098 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1099 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1102 BOOST_AUTO_TEST_CASE(test_edns_submask_by_domain
) {
1103 std::unique_ptr
<SyncRes
> sr
;
1108 const DNSName
target("powerdns.com.");
1109 SyncRes::addEDNSDomain(target
);
1111 EDNSSubnetOpts incomingECS
;
1112 incomingECS
.source
= Netmask("192.0.2.128/32");
1113 sr
->setIncomingECSFound(true);
1114 sr
->setIncomingECS(incomingECS
);
1116 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
, bool* chained
) {
1118 BOOST_REQUIRE(srcmask
);
1119 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1123 vector
<DNSRecord
> ret
;
1124 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1125 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1128 BOOST_AUTO_TEST_CASE(test_edns_submask_by_addr
) {
1129 std::unique_ptr
<SyncRes
> sr
;
1134 const DNSName
target("powerdns.com.");
1135 SyncRes::addEDNSSubnet(Netmask("192.0.2.1/32"));
1137 EDNSSubnetOpts incomingECS
;
1138 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1139 sr
->setIncomingECSFound(true);
1140 sr
->setIncomingECS(incomingECS
);
1142 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
, bool* chained
) {
1144 if (isRootServer(ip
)) {
1145 BOOST_REQUIRE(!srcmask
);
1147 setLWResult(res
, 0, false, false, true);
1148 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1149 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1151 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1153 BOOST_REQUIRE(srcmask
);
1154 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1156 setLWResult(res
, 0, true, false, false);
1157 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1164 vector
<DNSRecord
> ret
;
1165 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1166 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1167 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1168 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1169 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1172 BOOST_AUTO_TEST_CASE(test_following_cname
) {
1173 std::unique_ptr
<SyncRes
> sr
;
1178 const DNSName
target("cname.powerdns.com.");
1179 const DNSName
cnameTarget("cname-target.powerdns.com");
1181 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
, bool* chained
) {
1183 if (isRootServer(ip
)) {
1184 setLWResult(res
, 0, false, false, true);
1185 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1186 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1188 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1190 if (domain
== target
) {
1191 setLWResult(res
, 0, true, false, false);
1192 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1195 else if (domain
== cnameTarget
) {
1196 setLWResult(res
, 0, true, false, false);
1197 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1206 vector
<DNSRecord
> ret
;
1207 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1208 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1209 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1210 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1211 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1212 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1213 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1216 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
) {
1217 std::unique_ptr
<SyncRes
> sr
;
1222 const DNSName
target("cname.powerdns.com.");
1223 const DNSName
cnameTarget("cname-target.powerdns.com");
1225 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
, bool* chained
) {
1227 if (isRootServer(ip
)) {
1228 setLWResult(res
, 0, false, false, true);
1229 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1230 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1232 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1234 if (domain
== target
) {
1235 setLWResult(res
, RCode::NXDomain
, true, false, false);
1236 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1237 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1238 } else if (domain
== cnameTarget
) {
1239 setLWResult(res
, RCode::NXDomain
, true, false, false);
1240 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1250 vector
<DNSRecord
> ret
;
1251 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1252 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1253 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1254 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1255 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1256 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1258 /* a second time, to check the cache */
1260 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1261 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1262 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1263 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1264 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1265 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1268 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
) {
1269 std::unique_ptr
<SyncRes
> sr
;
1274 /* In this test we directly get the NS server for cname.powerdns.com.,
1275 and we don't know whether it's also authoritative for
1276 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1277 the additional A record for cname-target.powerdns.com. */
1278 const DNSName
target("cname.powerdns.com.");
1279 const DNSName
cnameTarget("cname-target.powerdns.com");
1281 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
, bool* chained
) {
1283 if (isRootServer(ip
)) {
1285 setLWResult(res
, 0, false, false, true);
1287 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1288 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1290 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1292 if (domain
== target
) {
1293 setLWResult(res
, 0, true, false, false);
1294 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1295 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1297 } else if (domain
== cnameTarget
) {
1298 setLWResult(res
, 0, true, false, false);
1299 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1309 vector
<DNSRecord
> ret
;
1310 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1311 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1312 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1313 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1314 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1315 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1316 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1317 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1318 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1321 BOOST_AUTO_TEST_CASE(test_cname_loop
) {
1322 std::unique_ptr
<SyncRes
> sr
;
1328 const DNSName
target("cname.powerdns.com.");
1330 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
, bool* chained
) {
1334 if (isRootServer(ip
)) {
1336 setLWResult(res
, 0, false, false, true);
1337 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1338 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1340 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1342 if (domain
== target
) {
1343 setLWResult(res
, 0, true, false, false);
1344 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1354 vector
<DNSRecord
> ret
;
1355 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1356 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1357 BOOST_CHECK_GT(ret
.size(), 0);
1358 BOOST_CHECK_EQUAL(count
, 2);
1361 BOOST_AUTO_TEST_CASE(test_cname_depth
) {
1362 std::unique_ptr
<SyncRes
> sr
;
1368 const DNSName
target("cname.powerdns.com.");
1370 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
, bool* chained
) {
1372 if (isRootServer(ip
)) {
1374 setLWResult(res
, 0, false, false, true);
1375 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1376 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1378 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1380 setLWResult(res
, 0, true, false, false);
1381 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(depth
) + "-cname.powerdns.com");
1389 vector
<DNSRecord
> ret
;
1390 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1391 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1392 BOOST_CHECK_EQUAL(ret
.size(), depth
);
1393 /* we have an arbitrary limit at 10 when following a CNAME chain */
1394 BOOST_CHECK_EQUAL(depth
, 10 + 2);
1397 BOOST_AUTO_TEST_CASE(test_time_limit
) {
1398 std::unique_ptr
<SyncRes
> sr
;
1404 const DNSName
target("cname.powerdns.com.");
1406 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
, bool* chained
) {
1410 if (isRootServer(ip
)) {
1411 setLWResult(res
, 0, false, false, true);
1412 /* Pretend that this query took 2000 ms */
1415 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1416 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1418 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1420 setLWResult(res
, 0, true, false, false);
1421 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1428 /* Set the maximum time to 1 ms */
1429 SyncRes::s_maxtotusec
= 1000;
1432 vector
<DNSRecord
> ret
;
1433 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1436 catch(const ImmediateServFailException
& e
) {
1438 BOOST_CHECK_EQUAL(queries
, 1);
1441 BOOST_AUTO_TEST_CASE(test_referral_depth
) {
1442 std::unique_ptr
<SyncRes
> sr
;
1448 const DNSName
target("www.powerdns.com.");
1450 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
, bool* chained
) {
1454 if (isRootServer(ip
)) {
1455 setLWResult(res
, 0, false, false, true);
1457 if (domain
== DNSName("www.powerdns.com.")) {
1458 addRecordToLW(res
, domain
, QType::NS
, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1460 else if (domain
== DNSName("ns.powerdns.com.")) {
1461 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1463 else if (domain
== DNSName("ns1.powerdns.org.")) {
1464 addRecordToLW(res
, domain
, QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1466 else if (domain
== DNSName("ns2.powerdns.org.")) {
1467 addRecordToLW(res
, domain
, QType::NS
, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1469 else if (domain
== DNSName("ns3.powerdns.org.")) {
1470 addRecordToLW(res
, domain
, QType::NS
, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1472 else if (domain
== DNSName("ns4.powerdns.org.")) {
1473 addRecordToLW(res
, domain
, QType::NS
, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1474 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::AUTHORITY
, 172800);
1478 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1480 setLWResult(res
, 0, true, false, false);
1481 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1488 /* Set the maximum depth low */
1489 SyncRes::s_maxdepth
= 10;
1492 vector
<DNSRecord
> ret
;
1493 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1496 catch(const ImmediateServFailException
& e
) {
1500 BOOST_AUTO_TEST_CASE(test_cname_qperq
) {
1501 std::unique_ptr
<SyncRes
> sr
;
1507 const DNSName
target("cname.powerdns.com.");
1509 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
, bool* chained
) {
1513 if (isRootServer(ip
)) {
1515 setLWResult(res
, 0, false, false, true);
1516 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1517 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1519 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1521 setLWResult(res
, 0, true, false, false);
1522 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(queries
) + "-cname.powerdns.com");
1529 /* Set the maximum number of questions very low */
1530 SyncRes::s_maxqperq
= 5;
1533 vector
<DNSRecord
> ret
;
1534 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1537 catch(const ImmediateServFailException
& e
) {
1538 BOOST_CHECK_EQUAL(queries
, SyncRes::s_maxqperq
);
1542 BOOST_AUTO_TEST_CASE(test_throttled_server
) {
1543 std::unique_ptr
<SyncRes
> sr
;
1548 const DNSName
target("throttled.powerdns.com.");
1549 const ComboAddress
ns("192.0.2.1:53");
1550 size_t queriesToNS
= 0;
1552 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
, bool* chained
) {
1554 if (isRootServer(ip
)) {
1556 setLWResult(res
, 0, false, false, true);
1557 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1558 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1560 } else if (ip
== ns
) {
1564 setLWResult(res
, 0, true, false, false);
1565 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1573 /* mark ns as down */
1574 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, 10000);
1576 vector
<DNSRecord
> ret
;
1577 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1578 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1579 BOOST_CHECK_EQUAL(ret
.size(), 0);
1580 /* we should not have sent any queries to ns */
1581 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1584 BOOST_AUTO_TEST_CASE(test_throttled_server_count
) {
1585 std::unique_ptr
<SyncRes
> sr
;
1590 const ComboAddress
ns("192.0.2.1:53");
1592 const size_t blocks
= 10;
1593 /* mark ns as down for 'blocks' queries */
1594 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, blocks
);
1596 for (size_t idx
= 0; idx
< blocks
; idx
++) {
1597 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1600 /* we have been throttled 'blocks' times, we should not be throttled anymore */
1601 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1604 BOOST_AUTO_TEST_CASE(test_throttled_server_time
) {
1605 std::unique_ptr
<SyncRes
> sr
;
1610 const ComboAddress
ns("192.0.2.1:53");
1612 const size_t seconds
= 1;
1613 /* mark ns as down for 'seconds' seconds */
1614 SyncRes::doThrottle(time(nullptr), ns
, seconds
, 10000);
1616 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1620 /* we should not be throttled anymore */
1621 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1624 BOOST_AUTO_TEST_CASE(test_dont_query_server
) {
1625 std::unique_ptr
<SyncRes
> sr
;
1630 const DNSName
target("throttled.powerdns.com.");
1631 const ComboAddress
ns("192.0.2.1:53");
1632 size_t queriesToNS
= 0;
1634 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
, bool* chained
) {
1636 if (isRootServer(ip
)) {
1638 setLWResult(res
, 0, false, false, true);
1639 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1640 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1642 } else if (ip
== ns
) {
1646 setLWResult(res
, 0, true, false, false);
1647 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1655 /* prevent querying this NS */
1656 SyncRes::addDontQuery(Netmask(ns
));
1658 vector
<DNSRecord
> ret
;
1659 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1660 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1661 BOOST_CHECK_EQUAL(ret
.size(), 0);
1662 /* we should not have sent any queries to ns */
1663 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1666 BOOST_AUTO_TEST_CASE(test_root_nx_trust
) {
1667 std::unique_ptr
<SyncRes
> sr
;
1672 const DNSName
target1("powerdns.com.");
1673 const DNSName
target2("notpowerdns.com.");
1674 const ComboAddress
ns("192.0.2.1:53");
1675 size_t queriesCount
= 0;
1677 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
, bool* chained
) {
1681 if (isRootServer(ip
)) {
1683 if (domain
== target1
) {
1684 setLWResult(res
, RCode::NXDomain
, true, false, true);
1685 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1688 setLWResult(res
, 0, true, false, true);
1689 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1690 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1694 } else if (ip
== ns
) {
1696 setLWResult(res
, 0, true, false, false);
1697 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1705 vector
<DNSRecord
> ret
;
1706 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1707 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1708 BOOST_CHECK_EQUAL(ret
.size(), 1);
1709 /* one for target1 and one for the entire TLD */
1710 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1713 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1714 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1715 BOOST_CHECK_EQUAL(ret
.size(), 1);
1716 /* one for target1 and one for the entire TLD */
1717 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1719 /* we should have sent only one query */
1720 BOOST_CHECK_EQUAL(queriesCount
, 1);
1723 BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific
) {
1724 std::unique_ptr
<SyncRes
> sr
;
1726 initSR(sr
, true, false);
1730 const DNSName
target1("powerdns.com.");
1731 const DNSName
target2("notpowerdns.com.");
1732 const ComboAddress
ns("192.0.2.1:53");
1733 size_t queriesCount
= 0;
1735 /* This time the root denies target1 with a "com." SOA instead of a "." one.
1736 We should add target1 to the negcache, but not "com.". */
1738 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
, bool* chained
) {
1742 if (isRootServer(ip
)) {
1744 if (domain
== target1
) {
1745 setLWResult(res
, RCode::NXDomain
, true, false, true);
1746 addRecordToLW(res
, "com.", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1749 setLWResult(res
, 0, true, false, true);
1750 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1751 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1755 } else if (ip
== ns
) {
1757 setLWResult(res
, 0, true, false, false);
1758 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1766 vector
<DNSRecord
> ret
;
1767 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1768 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1769 BOOST_CHECK_EQUAL(ret
.size(), 1);
1771 /* even with root-nx-trust on and a NX answer from the root,
1772 we should not have cached the entire TLD this time. */
1773 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1776 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1777 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1778 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1779 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1780 BOOST_CHECK_EQUAL(ret
[0].d_name
, target2
);
1781 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress("192.0.2.2"));
1783 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1785 BOOST_CHECK_EQUAL(queriesCount
, 3);
1788 BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust
) {
1789 std::unique_ptr
<SyncRes
> sr
;
1794 const DNSName
target1("powerdns.com.");
1795 const DNSName
target2("notpowerdns.com.");
1796 const ComboAddress
ns("192.0.2.1:53");
1797 size_t queriesCount
= 0;
1799 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
, bool* chained
) {
1803 if (isRootServer(ip
)) {
1805 if (domain
== target1
) {
1806 setLWResult(res
, RCode::NXDomain
, true, false, true);
1807 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1810 setLWResult(res
, 0, true, false, true);
1811 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1812 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1816 } else if (ip
== ns
) {
1818 setLWResult(res
, 0, true, false, false);
1819 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1827 SyncRes::s_rootNXTrust
= false;
1829 vector
<DNSRecord
> ret
;
1830 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1831 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1832 BOOST_CHECK_EQUAL(ret
.size(), 1);
1833 /* one for target1 */
1834 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1837 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1838 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1839 BOOST_CHECK_EQUAL(ret
.size(), 1);
1840 /* one for target1 */
1841 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1843 /* we should have sent three queries */
1844 BOOST_CHECK_EQUAL(queriesCount
, 3);
1847 BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response
) {
1848 std::unique_ptr
<SyncRes
> sr
;
1853 const DNSName
target("www.powerdns.com.");
1854 const DNSName
cnameTarget("cname.powerdns.com.");
1856 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
1858 EDNSSubnetOpts incomingECS
;
1859 incomingECS
.source
= Netmask("192.0.2.128/32");
1860 sr
->setIncomingECSFound(true);
1861 sr
->setIncomingECS(incomingECS
);
1863 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
, bool* chained
) {
1865 BOOST_REQUIRE(srcmask
);
1866 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1868 if (isRootServer(ip
)) {
1869 setLWResult(res
, 0, false, false, true);
1870 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1871 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1874 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1875 if (domain
== target
) {
1876 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
1877 setLWResult(res
, RCode::NXDomain
, true, false, true);
1878 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1879 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1881 else if (domain
== cnameTarget
) {
1882 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
1883 but we might if we still chase the CNAME. */
1884 setLWResult(res
, RCode::NXDomain
, true, false, true);
1885 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1894 vector
<DNSRecord
> ret
;
1895 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1896 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1897 BOOST_CHECK_EQUAL(ret
.size(), 2);
1898 /* no negative cache entry because the response was variable */
1899 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0);
1902 BOOST_AUTO_TEST_CASE(test_ns_speed
) {
1903 std::unique_ptr
<SyncRes
> sr
;
1908 const DNSName
target("powerdns.com.");
1910 std::map
<ComboAddress
, uint64_t> nsCounts
;
1912 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
, bool* chained
) {
1914 if (isRootServer(ip
)) {
1915 setLWResult(res
, 0, false, false, true);
1916 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1917 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1918 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1920 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1921 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1922 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1923 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 3600);
1924 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 3600);
1925 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 3600);
1931 if (ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("192.0.2.2:53")) {
1932 BOOST_CHECK_LT(nsCounts
.size(), 3);
1934 /* let's time out on pdns-public-ns2.powerdns.com. */
1937 else if (ip
== ComboAddress("192.0.2.1:53")) {
1938 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1940 setLWResult(res
, 0, true, false, true);
1941 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1952 gettimeofday(&now
, 0);
1954 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1955 then pdns-public-ns1.powerdns.com. on IPv4 */
1956 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now
);
1957 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now
);
1958 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now
);
1959 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now
);
1960 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now
);
1961 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now
);
1963 vector
<DNSRecord
> ret
;
1964 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1965 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1966 BOOST_CHECK_EQUAL(ret
.size(), 1);
1967 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1968 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.1:53")], 1);
1969 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.2:53")], 1);
1970 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("[2001:DB8::2]:53")], 1);
1973 BOOST_AUTO_TEST_CASE(test_flawed_nsset
) {
1974 std::unique_ptr
<SyncRes
> sr
;
1979 const DNSName
target("powerdns.com.");
1981 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
, bool* chained
) {
1983 if (isRootServer(ip
)) {
1984 setLWResult(res
, 0, false, false, true);
1985 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1987 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1990 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1991 setLWResult(res
, 0, true, false, true);
1992 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1999 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
2000 time_t now
= sr
->getNow().tv_sec
;
2001 std::vector
<DNSRecord
> records
;
2002 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
2003 addRecordToList(records
, target
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, now
+ 3600);
2005 t_RC
->replace(now
, target
, QType(QType::NS
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
2007 vector
<DNSRecord
> ret
;
2008 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2009 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2010 BOOST_CHECK_EQUAL(ret
.size(), 1);
2013 BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset
) {
2014 std::unique_ptr
<SyncRes
> sr
;
2019 const DNSName
target("powerdns.com.");
2020 size_t queriesCount
= 0;
2022 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
, bool* chained
) {
2026 if (isRootServer(ip
) && domain
== target
) {
2027 setLWResult(res
, 0, false, false, true);
2028 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2029 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2031 } else if (domain
== DNSName("pdns-public-ns2.powerdns.com.") || domain
== DNSName("pdns-public-ns3.powerdns.com.")){
2032 setLWResult(res
, 0, true, false, true);
2033 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
2040 vector
<DNSRecord
> ret
;
2041 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2042 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2043 BOOST_CHECK_EQUAL(ret
.size(), 0);
2044 /* one query to get NSs, then A and AAAA for each NS */
2045 BOOST_CHECK_EQUAL(queriesCount
, 5);
2048 BOOST_AUTO_TEST_CASE(test_cache_hit
) {
2049 std::unique_ptr
<SyncRes
> sr
;
2054 const DNSName
target("powerdns.com.");
2056 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
, bool* chained
) {
2061 /* we populate the cache with eveything we need */
2062 time_t now
= sr
->getNow().tv_sec
;
2063 std::vector
<DNSRecord
> records
;
2064 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
2066 addRecordToList(records
, target
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, now
+ 3600);
2067 t_RC
->replace(now
, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
2069 vector
<DNSRecord
> ret
;
2070 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2071 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2072 BOOST_CHECK_EQUAL(ret
.size(), 1);
2075 BOOST_AUTO_TEST_CASE(test_no_rd
) {
2076 std::unique_ptr
<SyncRes
> sr
;
2081 const DNSName
target("powerdns.com.");
2082 size_t queriesCount
= 0;
2086 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
, bool* chained
) {
2092 vector
<DNSRecord
> ret
;
2093 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2094 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2095 BOOST_CHECK_EQUAL(ret
.size(), 0);
2096 BOOST_CHECK_EQUAL(queriesCount
, 0);
2099 BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl
) {
2100 std::unique_ptr
<SyncRes
> sr
;
2105 const DNSName
target("cachettl.powerdns.com.");
2106 const ComboAddress
ns("192.0.2.1:53");
2108 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
, bool* chained
) {
2110 if (isRootServer(ip
)) {
2112 setLWResult(res
, 0, false, false, true);
2113 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2114 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 7200);
2116 } else if (ip
== ns
) {
2118 setLWResult(res
, 0, true, false, false);
2119 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
2127 const time_t now
= sr
->getNow().tv_sec
;
2128 SyncRes::s_minimumTTL
= 60;
2129 SyncRes::s_maxcachettl
= 3600;
2131 vector
<DNSRecord
> ret
;
2132 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2133 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2134 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2135 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumTTL
);
2137 const ComboAddress who
;
2138 vector
<DNSRecord
> cached
;
2139 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
2140 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2141 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2142 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
2145 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
2146 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2147 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2148 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
2151 BOOST_AUTO_TEST_CASE(test_cache_expired_ttl
) {
2152 std::unique_ptr
<SyncRes
> sr
;
2157 const DNSName
target("powerdns.com.");
2159 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
, bool* chained
) {
2161 if (isRootServer(ip
)) {
2162 setLWResult(res
, 0, false, false, true);
2163 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2165 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2168 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2169 setLWResult(res
, 0, true, false, true);
2170 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2177 /* we populate the cache with entries that expired 60s ago*/
2178 time_t now
= sr
->getNow().tv_sec
;
2179 std::vector
<DNSRecord
> records
;
2180 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
2181 addRecordToList(records
, target
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, now
- 60);
2183 t_RC
->replace(now
- 3600, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
2185 vector
<DNSRecord
> ret
;
2186 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2187 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2188 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2189 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
2190 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
2193 BOOST_AUTO_TEST_CASE(test_delegation_only
) {
2194 std::unique_ptr
<SyncRes
> sr
;
2199 /* Thanks, Verisign */
2200 SyncRes::addDelegationOnly(DNSName("com."));
2201 SyncRes::addDelegationOnly(DNSName("net."));
2203 const DNSName
target("nx-powerdns.com.");
2205 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
, bool* chained
) {
2207 if (isRootServer(ip
)) {
2208 setLWResult(res
, 0, false, false, true);
2209 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2210 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2212 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2214 setLWResult(res
, 0, true, false, true);
2215 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2222 vector
<DNSRecord
> ret
;
2223 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2224 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2225 BOOST_CHECK_EQUAL(ret
.size(), 0);
2228 BOOST_AUTO_TEST_CASE(test_unauth_any
) {
2229 std::unique_ptr
<SyncRes
> sr
;
2234 const DNSName
target("powerdns.com.");
2236 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
, bool* chained
) {
2238 if (isRootServer(ip
)) {
2239 setLWResult(res
, 0, false, false, true);
2240 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2241 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2243 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2245 setLWResult(res
, 0, false, false, true);
2246 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2253 vector
<DNSRecord
> ret
;
2254 int res
= sr
->beginResolve(target
, QType(QType::ANY
), QClass::IN
, ret
);
2255 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2256 BOOST_CHECK_EQUAL(ret
.size(), 0);
2259 BOOST_AUTO_TEST_CASE(test_no_data
) {
2260 std::unique_ptr
<SyncRes
> sr
;
2265 const DNSName
target("powerdns.com.");
2267 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
, bool* chained
) {
2269 setLWResult(res
, 0, true, false, true);
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(), 0);
2279 BOOST_AUTO_TEST_CASE(test_skip_opt_any
) {
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
, bool* chained
) {
2289 setLWResult(res
, 0, true, false, true);
2290 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2291 addRecordToLW(res
, domain
, QType::ANY
, "0 0");
2292 addRecordToLW(res
, domain
, QType::OPT
, "");
2296 vector
<DNSRecord
> ret
;
2297 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2298 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2299 BOOST_CHECK_EQUAL(ret
.size(), 1);
2302 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec
) {
2303 std::unique_ptr
<SyncRes
> sr
;
2308 const DNSName
target("powerdns.com.");
2310 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
, bool* chained
) {
2312 setLWResult(res
, 0, true, false, true);
2313 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2314 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2315 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2316 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2317 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2321 vector
<DNSRecord
> ret
;
2322 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2323 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2324 BOOST_CHECK_EQUAL(ret
.size(), 1);
2327 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec
) {
2328 std::unique_ptr
<SyncRes
> sr
;
2333 const DNSName
target("powerdns.com.");
2335 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
, bool* chained
) {
2337 setLWResult(res
, 0, true, false, true);
2338 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2339 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2340 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2341 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2342 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2346 vector
<DNSRecord
> ret
;
2347 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2348 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2349 BOOST_CHECK_EQUAL(ret
.size(), 4);
2352 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec
) {
2353 std::unique_ptr
<SyncRes
> sr
;
2358 const DNSName
target("powerdns.com.");
2360 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
, bool* chained
) {
2362 setLWResult(res
, RCode::NXDomain
, true, false, true);
2363 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2364 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2365 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2366 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2367 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2371 vector
<DNSRecord
> ret
;
2372 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2373 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2374 BOOST_CHECK_EQUAL(ret
.size(), 1);
2377 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec
) {
2378 std::unique_ptr
<SyncRes
> sr
;
2383 const DNSName
target("powerdns.com.");
2385 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
, bool* chained
) {
2387 setLWResult(res
, RCode::NXDomain
, true, false, true);
2388 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2389 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2390 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2391 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2392 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2396 vector
<DNSRecord
> ret
;
2397 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2398 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2399 BOOST_CHECK_EQUAL(ret
.size(), 4);
2402 BOOST_AUTO_TEST_CASE(test_qclass_none
) {
2403 std::unique_ptr
<SyncRes
> sr
;
2408 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
2409 size_t queriesCount
= 0;
2411 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
, bool* chained
) {
2417 const DNSName
target("powerdns.com.");
2418 vector
<DNSRecord
> ret
;
2419 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::NONE
, ret
);
2420 BOOST_CHECK_EQUAL(res
, -1);
2421 BOOST_CHECK_EQUAL(ret
.size(), 0);
2422 BOOST_CHECK_EQUAL(queriesCount
, 0);
2425 BOOST_AUTO_TEST_CASE(test_special_types
) {
2426 std::unique_ptr
<SyncRes
> sr
;
2431 /* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
2432 size_t queriesCount
= 0;
2434 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
, bool* chained
) {
2436 cerr
<<"asyncresolve called to ask "<<ip
.toStringWithPort()<<" about "<<domain
.toString()<<" / "<<QType(type
).getName()<<" over "<<(doTCP
? "TCP" : "UDP")<<" (rd: "<<sendRDQuery
<<", EDNS0 level: "<<EDNS0Level
<<")"<<endl
;
2441 const DNSName
target("powerdns.com.");
2442 vector
<DNSRecord
> ret
;
2443 int res
= sr
->beginResolve(target
, QType(QType::AXFR
), QClass::IN
, ret
);
2444 BOOST_CHECK_EQUAL(res
, -1);
2445 BOOST_CHECK_EQUAL(ret
.size(), 0);
2446 BOOST_CHECK_EQUAL(queriesCount
, 0);
2448 res
= sr
->beginResolve(target
, QType(QType::IXFR
), QClass::IN
, ret
);
2449 BOOST_CHECK_EQUAL(res
, -1);
2450 BOOST_CHECK_EQUAL(ret
.size(), 0);
2451 BOOST_CHECK_EQUAL(queriesCount
, 0);
2453 res
= sr
->beginResolve(target
, QType(QType::RRSIG
), QClass::IN
, ret
);
2454 BOOST_CHECK_EQUAL(res
, -1);
2455 BOOST_CHECK_EQUAL(ret
.size(), 0);
2456 BOOST_CHECK_EQUAL(queriesCount
, 0);
2458 res
= sr
->beginResolve(target
, QType(QType::NSEC3
), QClass::IN
, ret
);
2459 BOOST_CHECK_EQUAL(res
, -1);
2460 BOOST_CHECK_EQUAL(ret
.size(), 0);
2461 BOOST_CHECK_EQUAL(queriesCount
, 0);
2464 BOOST_AUTO_TEST_CASE(test_special_names
) {
2465 std::unique_ptr
<SyncRes
> sr
;
2470 /* special names should be handled internally */
2472 size_t queriesCount
= 0;
2474 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
, bool* chained
) {
2480 vector
<DNSRecord
> ret
;
2481 int res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
2482 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2483 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2484 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2485 BOOST_CHECK_EQUAL(queriesCount
, 0);
2488 res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
2489 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2490 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2491 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2492 BOOST_CHECK_EQUAL(queriesCount
, 0);
2495 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
);
2496 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2497 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2498 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2499 BOOST_CHECK_EQUAL(queriesCount
, 0);
2502 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
);
2503 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2504 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2505 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2506 BOOST_CHECK_EQUAL(queriesCount
, 0);
2509 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::A
), QClass::IN
, ret
);
2510 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2511 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2512 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2513 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), "127.0.0.1");
2514 BOOST_CHECK_EQUAL(queriesCount
, 0);
2517 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::AAAA
), QClass::IN
, ret
);
2518 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2519 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2520 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
2521 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(ret
[0])->getCA().toString(), "::1");
2522 BOOST_CHECK_EQUAL(queriesCount
, 0);
2525 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::ANY
), QClass::IN
, ret
);
2526 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2527 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2528 for (const auto& rec
: ret
) {
2529 BOOST_REQUIRE((rec
.d_type
== QType::A
) || rec
.d_type
== QType::AAAA
);
2530 if (rec
.d_type
== QType::A
) {
2531 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(rec
)->getCA().toString(), "127.0.0.1");
2534 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(rec
)->getCA().toString(), "::1");
2537 BOOST_CHECK_EQUAL(queriesCount
, 0);
2540 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2541 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2542 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2543 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2544 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2545 BOOST_CHECK_EQUAL(queriesCount
, 0);
2548 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2549 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2550 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2551 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2552 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2553 BOOST_CHECK_EQUAL(queriesCount
, 0);
2556 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2557 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2558 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2559 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2560 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2561 BOOST_CHECK_EQUAL(queriesCount
, 0);
2564 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2565 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2566 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2567 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2568 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2569 BOOST_CHECK_EQUAL(queriesCount
, 0);
2572 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2573 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2574 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2575 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2576 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2577 BOOST_CHECK_EQUAL(queriesCount
, 0);
2580 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2581 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2582 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2583 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2584 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2585 BOOST_CHECK_EQUAL(queriesCount
, 0);
2588 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz
) {
2589 std::unique_ptr
<SyncRes
> sr
;
2594 const DNSName
target("rpz.powerdns.com.");
2595 const ComboAddress
ns("192.0.2.1:53");
2597 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
, bool* chained
) {
2599 if (isRootServer(ip
)) {
2600 setLWResult(res
, false, true, false, true);
2601 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2602 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2604 } else if (ip
== ns
) {
2606 setLWResult(res
, 0, true, false, true);
2607 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2614 DNSFilterEngine::Policy pol
;
2615 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2616 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2617 zone
->setName("Unit test policy 0");
2618 zone
->addNSIPTrigger(Netmask(ns
, 32), pol
);
2619 auto luaconfsCopy
= g_luaconfs
.getCopy();
2620 luaconfsCopy
.dfe
.addZone(zone
);
2621 g_luaconfs
.setState(luaconfsCopy
);
2623 vector
<DNSRecord
> ret
;
2624 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2625 BOOST_CHECK_EQUAL(res
, -2);
2626 BOOST_CHECK_EQUAL(ret
.size(), 0);
2629 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz
) {
2630 std::unique_ptr
<SyncRes
> sr
;
2635 const DNSName
target("rpz.powerdns.com.");
2636 const ComboAddress
ns("[2001:DB8::42]:53");
2638 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
, bool* chained
) {
2640 if (isRootServer(ip
)) {
2641 setLWResult(res
, 0, false, false, true);
2642 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2643 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2645 } else if (ip
== ns
) {
2647 setLWResult(res
, 0, true, false, true);
2648 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2655 DNSFilterEngine::Policy pol
;
2656 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2657 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2658 zone
->setName("Unit test policy 0");
2659 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2660 auto luaconfsCopy
= g_luaconfs
.getCopy();
2661 luaconfsCopy
.dfe
.addZone(zone
);
2662 g_luaconfs
.setState(luaconfsCopy
);
2664 vector
<DNSRecord
> ret
;
2665 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2666 BOOST_CHECK_EQUAL(res
, -2);
2667 BOOST_CHECK_EQUAL(ret
.size(), 0);
2670 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz
) {
2671 std::unique_ptr
<SyncRes
> sr
;
2676 const DNSName
target("rpz.powerdns.com.");
2677 const ComboAddress
ns("192.0.2.1:53");
2678 const DNSName
nsName("ns1.powerdns.com.");
2680 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
, bool* chained
) {
2682 if (isRootServer(ip
)) {
2683 setLWResult(res
, 0, false, false, true);
2684 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2685 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2687 } else if (ip
== ns
) {
2689 setLWResult(res
, 0, true, false, true);
2690 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2697 DNSFilterEngine::Policy pol
;
2698 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2699 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2700 zone
->setName("Unit test policy 0");
2701 zone
->addNSTrigger(nsName
, pol
);
2702 auto luaconfsCopy
= g_luaconfs
.getCopy();
2703 luaconfsCopy
.dfe
.addZone(zone
);
2704 g_luaconfs
.setState(luaconfsCopy
);
2706 vector
<DNSRecord
> ret
;
2707 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2708 BOOST_CHECK_EQUAL(res
, -2);
2709 BOOST_CHECK_EQUAL(ret
.size(), 0);
2712 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled
) {
2713 std::unique_ptr
<SyncRes
> sr
;
2718 const DNSName
target("rpz.powerdns.com.");
2719 const ComboAddress
ns("192.0.2.1:53");
2720 const DNSName
nsName("ns1.powerdns.com.");
2722 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
, bool* chained
) {
2724 if (isRootServer(ip
)) {
2725 setLWResult(res
, 0, false, false, true);
2726 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2727 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2729 } else if (ip
== ns
) {
2731 setLWResult(res
, 0, true, false, true);
2732 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2739 DNSFilterEngine::Policy pol
;
2740 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2741 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2742 zone
->setName("Unit test policy 0");
2743 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2744 zone
->addNSTrigger(nsName
, pol
);
2745 auto luaconfsCopy
= g_luaconfs
.getCopy();
2746 luaconfsCopy
.dfe
.addZone(zone
);
2747 g_luaconfs
.setState(luaconfsCopy
);
2749 /* RPZ is disabled for this query, we should not be blocked */
2750 sr
->setWantsRPZ(false);
2752 vector
<DNSRecord
> ret
;
2753 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2754 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2755 BOOST_CHECK_EQUAL(ret
.size(), 1);
2758 BOOST_AUTO_TEST_CASE(test_forward_zone_nord
) {
2759 std::unique_ptr
<SyncRes
> sr
;
2764 const DNSName
target("powerdns.com.");
2765 const ComboAddress
ns("192.0.2.1:53");
2766 const ComboAddress
forwardedNS("192.0.2.42:53");
2768 SyncRes::AuthDomain ad
;
2769 ad
.d_rdForward
= false;
2770 ad
.d_servers
.push_back(forwardedNS
);
2771 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2773 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
, bool* chained
) {
2775 if (ip
== forwardedNS
) {
2776 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2778 setLWResult(res
, 0, true, false, true);
2779 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2786 /* simulate a no-RD query */
2789 vector
<DNSRecord
> ret
;
2790 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2791 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2792 BOOST_CHECK_EQUAL(ret
.size(), 1);
2795 BOOST_AUTO_TEST_CASE(test_forward_zone_rd
) {
2796 std::unique_ptr
<SyncRes
> sr
;
2801 const DNSName
target("powerdns.com.");
2802 const ComboAddress
ns("192.0.2.1:53");
2803 const ComboAddress
forwardedNS("192.0.2.42:53");
2805 size_t queriesCount
= 0;
2806 SyncRes::AuthDomain ad
;
2807 ad
.d_rdForward
= true;
2808 ad
.d_servers
.push_back(forwardedNS
);
2809 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2811 sr
->setAsyncCallback([forwardedNS
, &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
, bool* chained
) {
2815 if (ip
== forwardedNS
) {
2816 BOOST_CHECK_EQUAL(sendRDQuery
, true);
2818 /* set AA=0, we are a recursor */
2819 setLWResult(res
, 0, false, false, true);
2820 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2827 vector
<DNSRecord
> ret
;
2828 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2829 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2830 BOOST_CHECK_EQUAL(ret
.size(), 1);
2831 BOOST_CHECK_EQUAL(queriesCount
, 1);
2833 /* now make sure we can resolve from the cache (see #6340
2834 where the entries were added to the cache but not retrieved,
2835 because the recursor doesn't set the AA bit and we require
2836 it. We fixed it by not requiring the AA bit for forward-recurse
2839 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2840 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2841 BOOST_CHECK_EQUAL(ret
.size(), 1);
2842 BOOST_CHECK_EQUAL(queriesCount
, 1);
2845 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord
) {
2846 std::unique_ptr
<SyncRes
> sr
;
2851 const DNSName
target("powerdns.com.");
2852 const ComboAddress
ns("192.0.2.1:53");
2853 const ComboAddress
forwardedNS("192.0.2.42:53");
2855 SyncRes::AuthDomain ad
;
2856 ad
.d_rdForward
= true;
2857 ad
.d_servers
.push_back(forwardedNS
);
2858 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2860 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
, bool* chained
) {
2862 if (ip
== forwardedNS
) {
2863 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2865 setLWResult(res
, 0, true, false, true);
2866 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2873 /* simulate a no-RD query */
2876 vector
<DNSRecord
> ret
;
2877 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2878 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2879 BOOST_CHECK_EQUAL(ret
.size(), 1);
2882 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd
) {
2883 std::unique_ptr
<SyncRes
> sr
;
2888 const DNSName
target("powerdns.com.");
2889 const ComboAddress
ns("192.0.2.1:53");
2890 const ComboAddress
forwardedNS("192.0.2.42:53");
2892 SyncRes::AuthDomain ad
;
2893 ad
.d_rdForward
= true;
2894 ad
.d_servers
.push_back(forwardedNS
);
2895 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2897 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
, bool* chained
) {
2899 if (ip
== forwardedNS
) {
2900 BOOST_CHECK_EQUAL(sendRDQuery
, true);
2902 setLWResult(res
, 0, true, false, true);
2903 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2910 vector
<DNSRecord
> ret
;
2911 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2912 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2913 BOOST_CHECK_EQUAL(ret
.size(), 1);
2916 BOOST_AUTO_TEST_CASE(test_auth_zone_oob
) {
2917 std::unique_ptr
<SyncRes
> sr
;
2922 size_t queriesCount
= 0;
2923 const DNSName
target("test.xx.");
2924 const ComboAddress
targetAddr("127.0.0.1");
2925 const DNSName
authZone("test.xx");
2927 SyncRes::AuthDomain ad
;
2930 dr
.d_place
= DNSResourceRecord::ANSWER
;
2932 dr
.d_type
= QType::A
;
2934 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
2935 ad
.d_records
.insert(dr
);
2937 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
2939 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
, bool* chained
) {
2944 vector
<DNSRecord
> ret
;
2945 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2946 BOOST_CHECK_EQUAL(res
, 0);
2947 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2948 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2949 BOOST_CHECK_EQUAL(queriesCount
, 0);
2950 BOOST_CHECK(sr
->wasOutOfBand());
2951 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2953 /* a second time, to check that the OOB flag is set when the query cache is used */
2955 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2956 BOOST_CHECK_EQUAL(res
, 0);
2957 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2958 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2959 BOOST_CHECK_EQUAL(queriesCount
, 0);
2960 BOOST_CHECK(sr
->wasOutOfBand());
2961 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2963 /* a third time, to check that the validation is disabled when the OOB flag is set */
2965 sr
->setDNSSECValidationRequested(true);
2966 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2967 BOOST_CHECK_EQUAL(res
, 0);
2968 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2969 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2970 BOOST_CHECK_EQUAL(queriesCount
, 0);
2971 BOOST_CHECK(sr
->wasOutOfBand());
2972 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2975 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_cname
) {
2976 std::unique_ptr
<SyncRes
> sr
;
2981 size_t queriesCount
= 0;
2982 const DNSName
target("cname.test.xx.");
2983 const DNSName
targetCname("cname-target.test.xx.");
2984 const ComboAddress
targetCnameAddr("127.0.0.1");
2985 const DNSName
authZone("test.xx");
2987 SyncRes::AuthDomain ad
;
2990 dr
.d_place
= DNSResourceRecord::ANSWER
;
2992 dr
.d_type
= QType::CNAME
;
2994 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(targetCname
);
2995 ad
.d_records
.insert(dr
);
2997 dr
.d_place
= DNSResourceRecord::ANSWER
;
2998 dr
.d_name
= targetCname
;
2999 dr
.d_type
= QType::A
;
3001 dr
.d_content
= std::make_shared
<ARecordContent
>(targetCnameAddr
);
3002 ad
.d_records
.insert(dr
);
3004 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
3006 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
, bool* chained
) {
3011 vector
<DNSRecord
> ret
;
3012 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3013 BOOST_CHECK_EQUAL(res
, 0);
3014 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
3015 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3016 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3017 BOOST_CHECK_EQUAL(queriesCount
, 0);
3018 BOOST_CHECK(sr
->wasOutOfBand());
3019 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
3021 /* a second time, to check that the OOB flag is set when the query cache is used */
3023 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3024 BOOST_CHECK_EQUAL(res
, 0);
3025 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
3026 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3027 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3028 BOOST_CHECK_EQUAL(queriesCount
, 0);
3029 BOOST_CHECK(sr
->wasOutOfBand());
3030 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
3032 /* a third time, to check that the validation is disabled when the OOB flag is set */
3034 sr
->setDNSSECValidationRequested(true);
3035 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3036 BOOST_CHECK_EQUAL(res
, 0);
3037 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
3038 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3039 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3040 BOOST_CHECK_EQUAL(queriesCount
, 0);
3041 BOOST_CHECK(sr
->wasOutOfBand());
3042 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
3045 BOOST_AUTO_TEST_CASE(test_auth_zone
) {
3046 std::unique_ptr
<SyncRes
> sr
;
3051 size_t queriesCount
= 0;
3052 const DNSName
target("powerdns.com.");
3053 const ComboAddress
addr("192.0.2.5");
3055 SyncRes::AuthDomain ad
;
3058 dr
.d_place
= DNSResourceRecord::ANSWER
;
3060 dr
.d_type
= QType::SOA
;
3062 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3063 ad
.d_records
.insert(dr
);
3065 dr
.d_place
= DNSResourceRecord::ANSWER
;
3067 dr
.d_type
= QType::A
;
3069 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3070 ad
.d_records
.insert(dr
);
3072 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3073 (*map
)[target
] = ad
;
3074 SyncRes::setDomainMap(map
);
3076 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
, bool* chained
) {
3079 setLWResult(res
, 0, true, false, true);
3080 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
3084 vector
<DNSRecord
> ret
;
3085 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3086 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3087 BOOST_CHECK_EQUAL(ret
.size(), 1);
3088 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3089 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3090 BOOST_CHECK_EQUAL(queriesCount
, 0);
3093 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob
) {
3094 std::unique_ptr
<SyncRes
> sr
;
3099 size_t queriesCount
= 0;
3100 const DNSName
target("powerdns.com.");
3101 const DNSName
authZone("internal.powerdns.com.");
3102 const ComboAddress
addr("192.0.2.5");
3104 SyncRes::AuthDomain ad
;
3105 ad
.d_name
= authZone
;
3107 dr
.d_place
= DNSResourceRecord::ANSWER
;
3108 dr
.d_name
= authZone
;
3109 dr
.d_type
= QType::SOA
;
3111 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3112 ad
.d_records
.insert(dr
);
3114 dr
.d_place
= DNSResourceRecord::ANSWER
;
3115 dr
.d_name
= authZone
;
3116 dr
.d_type
= QType::A
;
3118 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3119 ad
.d_records
.insert(dr
);
3121 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3122 (*map
)[authZone
] = ad
;
3123 SyncRes::setDomainMap(map
);
3125 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
, bool* chained
) {
3129 if (domain
== target
) {
3130 setLWResult(res
, 0, true, false, true);
3131 addRecordToLW(res
, target
, QType::CNAME
, authZone
.toString(), DNSResourceRecord::ANSWER
, 3600);
3138 vector
<DNSRecord
> ret
;
3139 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3140 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3141 BOOST_CHECK_EQUAL(ret
.size(), 2);
3142 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3143 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), authZone
.toString());
3144 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3145 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
3146 BOOST_CHECK_EQUAL(queriesCount
, 1);
3149 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb
) {
3150 std::unique_ptr
<SyncRes
> sr
;
3155 size_t queriesCount
= 0;
3156 const DNSName
target("powerdns.com.");
3157 const DNSName
externalCNAME("www.open-xchange.com.");
3158 const ComboAddress
addr("192.0.2.5");
3160 SyncRes::AuthDomain ad
;
3163 dr
.d_place
= DNSResourceRecord::ANSWER
;
3165 dr
.d_type
= QType::SOA
;
3167 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3168 ad
.d_records
.insert(dr
);
3170 dr
.d_place
= DNSResourceRecord::ANSWER
;
3172 dr
.d_type
= QType::CNAME
;
3174 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(externalCNAME
);
3175 ad
.d_records
.insert(dr
);
3177 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3178 (*map
)[target
] = ad
;
3179 SyncRes::setDomainMap(map
);
3181 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
, bool* chained
) {
3185 if (domain
== externalCNAME
) {
3186 setLWResult(res
, 0, true, false, true);
3187 addRecordToLW(res
, externalCNAME
, QType::A
, addr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3194 vector
<DNSRecord
> ret
;
3195 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3196 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3197 BOOST_CHECK_EQUAL(ret
.size(), 2);
3198 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3199 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), externalCNAME
.toString());
3200 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3201 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
3202 BOOST_CHECK_EQUAL(queriesCount
, 1);
3205 BOOST_AUTO_TEST_CASE(test_auth_zone_nodata
) {
3206 std::unique_ptr
<SyncRes
> sr
;
3211 size_t queriesCount
= 0;
3212 const DNSName
target("nodata.powerdns.com.");
3213 const DNSName
authZone("powerdns.com");
3215 SyncRes::AuthDomain ad
;
3216 ad
.d_name
= authZone
;
3218 dr
.d_place
= DNSResourceRecord::ANSWER
;
3220 dr
.d_type
= QType::A
;
3222 dr
.d_content
= std::make_shared
<ARecordContent
>(ComboAddress("192.0.2.1"));
3223 ad
.d_records
.insert(dr
);
3225 dr
.d_place
= DNSResourceRecord::ANSWER
;
3226 dr
.d_name
= authZone
;
3227 dr
.d_type
= QType::SOA
;
3229 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3230 ad
.d_records
.insert(dr
);
3232 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3233 (*map
)[authZone
] = ad
;
3234 SyncRes::setDomainMap(map
);
3236 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
, bool* chained
) {
3243 vector
<DNSRecord
> ret
;
3244 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3245 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3246 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3247 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3248 BOOST_CHECK_EQUAL(queriesCount
, 0);
3251 BOOST_AUTO_TEST_CASE(test_auth_zone_nx
) {
3252 std::unique_ptr
<SyncRes
> sr
;
3257 size_t queriesCount
= 0;
3258 const DNSName
target("nx.powerdns.com.");
3259 const DNSName
authZone("powerdns.com");
3261 SyncRes::AuthDomain ad
;
3262 ad
.d_name
= authZone
;
3264 dr
.d_place
= DNSResourceRecord::ANSWER
;
3265 dr
.d_name
= DNSName("powerdns.com.");
3266 dr
.d_type
= QType::SOA
;
3268 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3269 ad
.d_records
.insert(dr
);
3271 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3272 (*map
)[authZone
] = ad
;
3273 SyncRes::setDomainMap(map
);
3275 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
, bool* chained
) {
3282 vector
<DNSRecord
> ret
;
3283 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3284 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
3285 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3286 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3287 BOOST_CHECK_EQUAL(queriesCount
, 0);
3290 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation
) {
3291 std::unique_ptr
<SyncRes
> sr
;
3292 initSR(sr
, true, false);
3296 size_t queriesCount
= 0;
3297 const DNSName
target("www.test.powerdns.com.");
3298 const ComboAddress
targetAddr("192.0.2.2");
3299 const DNSName
ns("ns1.test.powerdns.com.");
3300 const ComboAddress
nsAddr("192.0.2.1");
3301 const DNSName
authZone("powerdns.com");
3303 SyncRes::AuthDomain ad
;
3304 ad
.d_name
= authZone
;
3306 dr
.d_place
= DNSResourceRecord::ANSWER
;
3307 dr
.d_name
= authZone
;
3308 dr
.d_type
= QType::SOA
;
3310 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3311 ad
.d_records
.insert(dr
);
3313 dr
.d_place
= DNSResourceRecord::ANSWER
;
3314 dr
.d_name
= DNSName("test.powerdns.com.");
3315 dr
.d_type
= QType::NS
;
3317 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3318 ad
.d_records
.insert(dr
);
3320 dr
.d_place
= DNSResourceRecord::ANSWER
;
3322 dr
.d_type
= QType::A
;
3324 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3325 ad
.d_records
.insert(dr
);
3327 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3328 (*map
)[authZone
] = ad
;
3329 SyncRes::setDomainMap(map
);
3332 auto luaconfsCopy
= g_luaconfs
.getCopy();
3333 luaconfsCopy
.dsAnchors
.clear();
3334 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
3335 g_luaconfs
.setState(luaconfsCopy
);
3337 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
, bool* chained
) {
3340 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
3341 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
, domain
== authZone
);
3344 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3345 setLWResult(res
, 0, true, false, true);
3346 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3353 sr
->setDNSSECValidationRequested(true);
3354 vector
<DNSRecord
> ret
;
3355 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3356 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3357 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3358 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3359 BOOST_CHECK_EQUAL(queriesCount
, 4);
3360 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
3363 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point
) {
3364 std::unique_ptr
<SyncRes
> sr
;
3369 size_t queriesCount
= 0;
3370 const DNSName
target("test.powerdns.com.");
3371 const ComboAddress
targetAddr("192.0.2.2");
3372 const DNSName
ns("ns1.test.powerdns.com.");
3373 const ComboAddress
nsAddr("192.0.2.1");
3374 const DNSName
authZone("powerdns.com");
3376 SyncRes::AuthDomain ad
;
3377 ad
.d_name
= authZone
;
3379 dr
.d_place
= DNSResourceRecord::ANSWER
;
3380 dr
.d_name
= authZone
;
3381 dr
.d_type
= QType::SOA
;
3383 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3384 ad
.d_records
.insert(dr
);
3386 dr
.d_place
= DNSResourceRecord::ANSWER
;
3387 dr
.d_name
= DNSName("test.powerdns.com.");
3388 dr
.d_type
= QType::NS
;
3390 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3391 ad
.d_records
.insert(dr
);
3393 dr
.d_place
= DNSResourceRecord::ANSWER
;
3395 dr
.d_type
= QType::A
;
3397 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3398 ad
.d_records
.insert(dr
);
3400 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3401 (*map
)[authZone
] = ad
;
3402 SyncRes::setDomainMap(map
);
3404 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
, bool* chained
) {
3408 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3409 setLWResult(res
, 0, true, false, true);
3410 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3417 vector
<DNSRecord
> ret
;
3418 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3419 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3420 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3421 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3422 BOOST_CHECK_EQUAL(queriesCount
, 1);
3425 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard
) {
3426 std::unique_ptr
<SyncRes
> sr
;
3431 size_t queriesCount
= 0;
3432 const DNSName
target("test.powerdns.com.");
3433 const ComboAddress
targetAddr("192.0.2.2");
3434 const DNSName
authZone("powerdns.com");
3436 SyncRes::AuthDomain ad
;
3437 ad
.d_name
= authZone
;
3439 dr
.d_place
= DNSResourceRecord::ANSWER
;
3440 dr
.d_name
= authZone
;
3441 dr
.d_type
= QType::SOA
;
3443 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3444 ad
.d_records
.insert(dr
);
3446 dr
.d_place
= DNSResourceRecord::ANSWER
;
3447 dr
.d_name
= DNSName("*.powerdns.com.");
3448 dr
.d_type
= QType::A
;
3450 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3451 ad
.d_records
.insert(dr
);
3453 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3454 (*map
)[authZone
] = ad
;
3455 SyncRes::setDomainMap(map
);
3457 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
, bool* chained
) {
3464 vector
<DNSRecord
> ret
;
3465 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3466 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3467 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3468 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3469 BOOST_CHECK_EQUAL(queriesCount
, 0);
3472 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata
) {
3473 std::unique_ptr
<SyncRes
> sr
;
3478 size_t queriesCount
= 0;
3479 const DNSName
target("test.powerdns.com.");
3480 const ComboAddress
targetAddr("192.0.2.2");
3481 const DNSName
authZone("powerdns.com");
3483 SyncRes::AuthDomain ad
;
3484 ad
.d_name
= authZone
;
3486 dr
.d_place
= DNSResourceRecord::ANSWER
;
3487 dr
.d_name
= authZone
;
3488 dr
.d_type
= QType::SOA
;
3490 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3491 ad
.d_records
.insert(dr
);
3493 dr
.d_place
= DNSResourceRecord::ANSWER
;
3494 dr
.d_name
= DNSName("*.powerdns.com.");
3495 dr
.d_type
= QType::A
;
3497 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3498 ad
.d_records
.insert(dr
);
3500 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3501 (*map
)[authZone
] = ad
;
3502 SyncRes::setDomainMap(map
);
3504 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
, bool* chained
) {
3511 vector
<DNSRecord
> ret
;
3512 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3513 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3514 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3515 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3516 BOOST_CHECK_EQUAL(queriesCount
, 0);
3519 BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only
) {
3520 std::unique_ptr
<SyncRes
> sr
;
3525 size_t queriesCount
= 0;
3526 const DNSName
target("powerdns.com.");
3527 const ComboAddress
addr("192.0.2.5");
3529 SyncRes::AuthDomain ad
;
3532 dr
.d_place
= DNSResourceRecord::ANSWER
;
3534 dr
.d_type
= QType::SOA
;
3536 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3537 ad
.d_records
.insert(dr
);
3539 dr
.d_place
= DNSResourceRecord::ANSWER
;
3541 dr
.d_type
= QType::A
;
3543 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3544 ad
.d_records
.insert(dr
);
3546 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3547 (*map
)[target
] = ad
;
3548 SyncRes::setDomainMap(map
);
3550 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
, bool* chained
) {
3553 setLWResult(res
, 0, true, false, true);
3554 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
3558 /* simulate a no-RD query */
3561 vector
<DNSRecord
> ret
;
3562 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3563 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3564 BOOST_CHECK_EQUAL(ret
.size(), 1);
3565 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3566 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3567 BOOST_CHECK_EQUAL(queriesCount
, 0);
3570 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig
) {
3573 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3574 dcke
->create(dcke
->getBits());
3575 // cerr<<dcke->convertToISC()<<endl;
3576 DNSSECPrivateKey dpk
;
3580 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
3581 recordcontents
.push_back(getRecordContent(QType::A
, "192.0.2.1"));
3583 DNSName
qname("powerdns.com.");
3585 time_t now
= time(nullptr);
3586 RRSIGRecordContent rrc
;
3587 /* this RRSIG is valid for the current second only */
3588 computeRRSIG(dpk
, qname
, qname
, QType::A
, 600, 0, rrc
, recordcontents
, boost::none
, now
);
3591 keyset
.insert(std::make_shared
<DNSKEYRecordContent
>(dpk
.getDNSKEY()));
3593 std::vector
<std::shared_ptr
<RRSIGRecordContent
> > sigs
;
3594 sigs
.push_back(std::make_shared
<RRSIGRecordContent
>(rrc
));
3596 BOOST_CHECK(validateWithKeySet(now
, qname
, recordcontents
, sigs
, keyset
));
3599 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk
) {
3600 std::unique_ptr
<SyncRes
> sr
;
3603 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3606 const DNSName
target(".");
3609 auto luaconfsCopy
= g_luaconfs
.getCopy();
3610 luaconfsCopy
.dsAnchors
.clear();
3611 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3612 g_luaconfs
.setState(luaconfsCopy
);
3614 size_t queriesCount
= 0;
3616 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
, bool* chained
) {
3619 if (domain
== target
&& type
== QType::NS
) {
3621 setLWResult(res
, 0, true, false, true);
3622 char addr
[] = "a.root-servers.net.";
3623 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3625 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3628 addRRSIG(keys
, res
->d_records
, domain
, 300);
3630 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3631 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3634 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3636 setLWResult(res
, 0, true, false, true);
3638 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3639 addRRSIG(keys
, res
->d_records
, domain
, 300);
3647 vector
<DNSRecord
> ret
;
3648 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3649 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3650 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3651 /* 13 NS + 1 RRSIG */
3652 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3653 BOOST_CHECK_EQUAL(queriesCount
, 2);
3655 /* again, to test the cache */
3657 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3658 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3659 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3660 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3661 BOOST_CHECK_EQUAL(queriesCount
, 2);
3664 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk
) {
3665 std::unique_ptr
<SyncRes
> sr
;
3668 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3671 const DNSName
target(".");
3672 testkeysset_t zskeys
;
3673 testkeysset_t kskeys
;
3675 /* Generate key material for "." */
3676 auto dckeZ
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3677 dckeZ
->create(dckeZ
->getBits());
3678 DNSSECPrivateKey ksk
;
3681 DSRecordContent kskds
= makeDSFromDNSKey(target
, ksk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3683 auto dckeK
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3684 dckeK
->create(dckeK
->getBits());
3685 DNSSECPrivateKey zsk
;
3688 DSRecordContent zskds
= makeDSFromDNSKey(target
, zsk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3690 kskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(ksk
, kskds
);
3691 zskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(zsk
, zskds
);
3693 /* Set the root DS */
3694 auto luaconfsCopy
= g_luaconfs
.getCopy();
3695 luaconfsCopy
.dsAnchors
.clear();
3696 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(kskds
);
3697 g_luaconfs
.setState(luaconfsCopy
);
3699 size_t queriesCount
= 0;
3701 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
, bool* chained
) {
3704 if (domain
== target
&& type
== QType::NS
) {
3706 setLWResult(res
, 0, true, false, true);
3707 char addr
[] = "a.root-servers.net.";
3708 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3710 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3713 addRRSIG(zskeys
, res
->d_records
, domain
, 300);
3715 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3716 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3719 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3721 setLWResult(res
, 0, true, false, true);
3723 addDNSKEY(kskeys
, domain
, 300, res
->d_records
);
3724 addDNSKEY(zskeys
, domain
, 300, res
->d_records
);
3725 addRRSIG(kskeys
, res
->d_records
, domain
, 300);
3733 vector
<DNSRecord
> ret
;
3734 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3735 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3736 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3737 /* 13 NS + 1 RRSIG */
3738 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3739 BOOST_CHECK_EQUAL(queriesCount
, 2);
3741 /* again, to test the cache */
3743 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3744 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3745 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3746 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3747 BOOST_CHECK_EQUAL(queriesCount
, 2);
3750 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey
) {
3751 std::unique_ptr
<SyncRes
> sr
;
3754 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3757 const DNSName
target(".");
3760 auto luaconfsCopy
= g_luaconfs
.getCopy();
3761 luaconfsCopy
.dsAnchors
.clear();
3762 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3763 g_luaconfs
.setState(luaconfsCopy
);
3765 size_t queriesCount
= 0;
3767 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
, bool* chained
) {
3770 if (domain
== target
&& type
== QType::NS
) {
3772 setLWResult(res
, 0, true, false, true);
3773 char addr
[] = "a.root-servers.net.";
3774 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3776 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3779 addRRSIG(keys
, res
->d_records
, domain
, 300);
3781 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3782 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3785 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3787 setLWResult(res
, 0, true, false, true);
3797 vector
<DNSRecord
> ret
;
3798 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3799 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3800 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3801 /* 13 NS + 1 RRSIG */
3802 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3803 BOOST_CHECK_EQUAL(queriesCount
, 2);
3805 /* again, to test the cache */
3807 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3808 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3809 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3810 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3811 BOOST_CHECK_EQUAL(queriesCount
, 2);
3814 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds
) {
3815 std::unique_ptr
<SyncRes
> sr
;
3818 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3821 const DNSName
target(".");
3822 testkeysset_t dskeys
;
3825 /* Generate key material for "." */
3826 auto dckeDS
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3827 dckeDS
->create(dckeDS
->getBits());
3828 DNSSECPrivateKey dskey
;
3829 dskey
.d_flags
= 257;
3830 dskey
.setKey(dckeDS
);
3831 DSRecordContent drc
= makeDSFromDNSKey(target
, dskey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3833 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3834 dcke
->create(dcke
->getBits());
3835 DNSSECPrivateKey dpk
;
3838 DSRecordContent uselessdrc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3840 dskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dskey
, drc
);
3841 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, uselessdrc
);
3843 /* Set the root DS */
3844 auto luaconfsCopy
= g_luaconfs
.getCopy();
3845 luaconfsCopy
.dsAnchors
.clear();
3846 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3847 g_luaconfs
.setState(luaconfsCopy
);
3849 size_t queriesCount
= 0;
3851 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
, bool* chained
) {
3854 if (domain
== target
&& type
== QType::NS
) {
3856 setLWResult(res
, 0, true, false, true);
3857 char addr
[] = "a.root-servers.net.";
3858 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3860 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3863 addRRSIG(keys
, res
->d_records
, domain
, 300);
3865 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3866 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3869 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3871 setLWResult(res
, 0, true, false, true);
3873 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3874 addRRSIG(keys
, res
->d_records
, domain
, 300);
3882 vector
<DNSRecord
> ret
;
3883 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3884 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3885 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3886 /* 13 NS + 1 RRSIG */
3887 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3888 BOOST_CHECK_EQUAL(queriesCount
, 2);
3890 /* again, to test the cache */
3892 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3893 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3894 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3895 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3896 BOOST_CHECK_EQUAL(queriesCount
, 2);
3899 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey
) {
3900 std::unique_ptr
<SyncRes
> sr
;
3903 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3906 const DNSName
target(".");
3908 testkeysset_t rrsigkeys
;
3910 auto luaconfsCopy
= g_luaconfs
.getCopy();
3911 luaconfsCopy
.dsAnchors
.clear();
3912 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3913 g_luaconfs
.setState(luaconfsCopy
);
3915 auto dckeRRSIG
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3916 dckeRRSIG
->create(dckeRRSIG
->getBits());
3917 DNSSECPrivateKey rrsigkey
;
3918 rrsigkey
.d_flags
= 257;
3919 rrsigkey
.setKey(dckeRRSIG
);
3920 DSRecordContent rrsigds
= makeDSFromDNSKey(target
, rrsigkey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3922 rrsigkeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(rrsigkey
, rrsigds
);
3924 size_t queriesCount
= 0;
3926 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
, bool* chained
) {
3929 if (domain
== target
&& type
== QType::NS
) {
3931 setLWResult(res
, 0, true, false, true);
3932 char addr
[] = "a.root-servers.net.";
3933 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3935 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3938 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3940 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3941 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3944 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3946 setLWResult(res
, 0, true, false, true);
3948 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3949 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3957 vector
<DNSRecord
> ret
;
3958 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3959 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3960 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3961 /* 13 NS + 1 RRSIG */
3962 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3963 BOOST_CHECK_EQUAL(queriesCount
, 2);
3965 /* again, to test the cache */
3967 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3968 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3969 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3970 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3971 BOOST_CHECK_EQUAL(queriesCount
, 2);
3974 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig
) {
3975 std::unique_ptr
<SyncRes
> sr
;
3978 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3981 const DNSName
target(".");
3984 auto luaconfsCopy
= g_luaconfs
.getCopy();
3985 luaconfsCopy
.dsAnchors
.clear();
3986 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3987 g_luaconfs
.setState(luaconfsCopy
);
3989 size_t queriesCount
= 0;
3991 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
, bool* chained
) {
3994 if (domain
== target
&& type
== QType::NS
) {
3996 setLWResult(res
, 0, true, false, true);
3997 char addr
[] = "a.root-servers.net.";
3998 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4000 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4005 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4006 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4009 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4011 setLWResult(res
, 0, true, false, true);
4013 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4014 addRRSIG(keys
, res
->d_records
, domain
, 300);
4022 vector
<DNSRecord
> ret
;
4023 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4024 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4025 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4026 /* 13 NS + 0 RRSIG */
4027 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
4028 /* no RRSIG so no query for DNSKEYs */
4029 BOOST_CHECK_EQUAL(queriesCount
, 1);
4031 /* again, to test the cache */
4033 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4034 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4035 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4036 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
4037 BOOST_CHECK_EQUAL(queriesCount
, 1);
4040 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm
) {
4041 std::unique_ptr
<SyncRes
> sr
;
4044 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4047 const DNSName
target(".");
4050 /* Generate key material for "." */
4051 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
4052 dcke
->create(dcke
->getBits());
4053 DNSSECPrivateKey dpk
;
4056 /* Fake algorithm number (private) */
4057 dpk
.d_algorithm
= 253;
4059 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
4060 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, drc
);
4061 /* Fake algorithm number (private) */
4062 drc
.d_algorithm
= 253;
4064 /* Set the root DS */
4065 auto luaconfsCopy
= g_luaconfs
.getCopy();
4066 luaconfsCopy
.dsAnchors
.clear();
4067 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
4068 g_luaconfs
.setState(luaconfsCopy
);
4070 size_t queriesCount
= 0;
4072 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
, bool* chained
) {
4075 if (domain
== target
&& type
== QType::NS
) {
4077 setLWResult(res
, 0, true, false, true);
4078 char addr
[] = "a.root-servers.net.";
4079 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4081 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4084 addRRSIG(keys
, res
->d_records
, domain
, 300);
4086 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4087 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4090 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4092 setLWResult(res
, 0, true, false, true);
4094 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4095 addRRSIG(keys
, res
->d_records
, domain
, 300);
4103 vector
<DNSRecord
> ret
;
4104 int 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 /* 13 NS + 1 RRSIG */
4108 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4109 /* no supported DS so no query for DNSKEYs */
4110 BOOST_CHECK_EQUAL(queriesCount
, 1);
4112 /* again, to test the cache */
4114 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4115 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4116 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4117 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4118 BOOST_CHECK_EQUAL(queriesCount
, 1);
4121 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest
) {
4122 std::unique_ptr
<SyncRes
> sr
;
4125 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4128 const DNSName
target(".");
4131 /* Generate key material for "." */
4132 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
4133 dcke
->create(dcke
->getBits());
4134 DNSSECPrivateKey dpk
;
4137 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
4138 /* Fake digest number (reserved) */
4139 drc
.d_digesttype
= 0;
4141 keys
[target
] = std::pair
<DNSSECPrivateKey
, DSRecordContent
>(dpk
, drc
);
4143 /* Set the root DS */
4144 auto luaconfsCopy
= g_luaconfs
.getCopy();
4145 luaconfsCopy
.dsAnchors
.clear();
4146 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
4147 g_luaconfs
.setState(luaconfsCopy
);
4149 size_t queriesCount
= 0;
4151 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
, bool* chained
) {
4154 if (domain
== target
&& type
== QType::NS
) {
4156 setLWResult(res
, 0, true, false, true);
4157 char addr
[] = "a.root-servers.net.";
4158 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4160 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4163 addRRSIG(keys
, res
->d_records
, domain
, 300);
4165 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4166 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4169 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4171 setLWResult(res
, 0, true, false, true);
4173 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4174 addRRSIG(keys
, res
->d_records
, domain
, 300);
4182 vector
<DNSRecord
> ret
;
4183 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4184 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4185 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4186 /* 13 NS + 1 RRSIG */
4187 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4188 /* no supported DS so no query for DNSKEYs */
4189 BOOST_CHECK_EQUAL(queriesCount
, 1);
4191 /* again, to test the cache */
4193 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4194 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4195 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4196 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4197 BOOST_CHECK_EQUAL(queriesCount
, 1);
4200 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig
) {
4201 std::unique_ptr
<SyncRes
> sr
;
4204 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4207 const DNSName
target(".");
4210 auto luaconfsCopy
= g_luaconfs
.getCopy();
4211 luaconfsCopy
.dsAnchors
.clear();
4212 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4214 g_luaconfs
.setState(luaconfsCopy
);
4216 size_t queriesCount
= 0;
4218 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
, bool* chained
) {
4221 if (domain
== target
&& type
== QType::NS
) {
4223 setLWResult(res
, 0, true, false, true);
4224 char addr
[] = "a.root-servers.net.";
4225 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4227 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4230 addRRSIG(keys
, res
->d_records
, domain
, 300, true);
4232 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4233 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4236 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4238 setLWResult(res
, 0, true, false, true);
4240 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4241 addRRSIG(keys
, res
->d_records
, domain
, 300);
4249 vector
<DNSRecord
> ret
;
4250 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4251 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4252 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4253 /* 13 NS + 1 RRSIG */
4254 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4255 BOOST_CHECK_EQUAL(queriesCount
, 2);
4257 /* again, to test the cache */
4259 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4260 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4261 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4262 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4263 BOOST_CHECK_EQUAL(queriesCount
, 2);
4266 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo
) {
4267 std::unique_ptr
<SyncRes
> sr
;
4270 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4273 const DNSName
target(".");
4276 auto luaconfsCopy
= g_luaconfs
.getCopy();
4277 luaconfsCopy
.dsAnchors
.clear();
4278 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4280 g_luaconfs
.setState(luaconfsCopy
);
4282 size_t queriesCount
= 0;
4284 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
, bool* chained
) {
4287 if (domain
== target
&& type
== QType::NS
) {
4289 setLWResult(res
, 0, true, false, true);
4290 char addr
[] = "a.root-servers.net.";
4291 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4293 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4296 /* FORCE WRONG ALGO */
4297 addRRSIG(keys
, res
->d_records
, domain
, 300, false, DNSSECKeeper::RSASHA256
);
4299 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4300 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4303 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4305 setLWResult(res
, 0, true, false, true);
4307 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4308 addRRSIG(keys
, res
->d_records
, domain
, 300);
4316 vector
<DNSRecord
> ret
;
4317 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4318 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4319 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4320 /* 13 NS + 1 RRSIG */
4321 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4322 BOOST_CHECK_EQUAL(queriesCount
, 2);
4324 /* again, to test the cache */
4326 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4327 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4328 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4329 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4330 BOOST_CHECK_EQUAL(queriesCount
, 2);
4333 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds
) {
4334 std::unique_ptr
<SyncRes
> sr
;
4337 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4340 const DNSName
target("com.");
4341 const ComboAddress
targetAddr("192.0.2.42");
4344 auto luaconfsCopy
= g_luaconfs
.getCopy();
4345 luaconfsCopy
.dsAnchors
.clear();
4346 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4347 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4349 g_luaconfs
.setState(luaconfsCopy
);
4351 size_t queriesCount
= 0;
4353 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
, bool* chained
) {
4356 DNSName auth
= domain
;
4358 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4359 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
) == 0) {
4363 if (type
== QType::DS
&& domain
== target
) {
4364 /* remove the last record, which is the DS's RRSIG */
4365 res
->d_records
.pop_back();
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 /* Include the DS but omit the RRSIG*/
4375 addDS(DNSName("com."), 300, res
->d_records
, keys
);
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 setLWResult(res
, RCode::NoError
, true, false, true);
4382 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4383 addRRSIG(keys
, res
->d_records
, auth
, 300);
4390 vector
<DNSRecord
> ret
;
4391 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4392 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4393 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4394 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4395 BOOST_CHECK_EQUAL(queriesCount
, 4);
4397 /* again, to test the cache */
4399 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4400 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4401 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4402 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4403 BOOST_CHECK_EQUAL(queriesCount
, 4);
4405 /* now we ask directly for the DS */
4407 res
= sr
->beginResolve(DNSName("com."), QType(QType::DS
), QClass::IN
, ret
);
4408 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4409 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4410 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4411 BOOST_CHECK_EQUAL(queriesCount
, 4);
4414 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds_direct
) {
4415 std::unique_ptr
<SyncRes
> sr
;
4418 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4421 const DNSName
target("com.");
4424 auto luaconfsCopy
= g_luaconfs
.getCopy();
4425 luaconfsCopy
.dsAnchors
.clear();
4426 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4427 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4429 g_luaconfs
.setState(luaconfsCopy
);
4431 size_t queriesCount
= 0;
4433 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
, bool* chained
) {
4436 DNSName auth
= domain
;
4438 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4439 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
) == 0) {
4443 if (type
== QType::DS
&& domain
== target
) {
4444 /* remove the last record, which is the DS's RRSIG */
4445 res
->d_records
.pop_back();
4451 if (isRootServer(ip
)) {
4452 setLWResult(res
, 0, false, false, true);
4453 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4454 /* Include the DS but omit the RRSIG*/
4455 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4456 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4463 vector
<DNSRecord
> ret
;
4464 int res
= sr
->beginResolve(DNSName("com."), QType(QType::DS
), QClass::IN
, ret
);
4465 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4466 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4467 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4468 BOOST_CHECK_EQUAL(queriesCount
, 1);
4471 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos
) {
4472 std::unique_ptr
<SyncRes
> sr
;
4475 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4478 const DNSName
target("powerdns.com.");
4479 const ComboAddress
targetAddr("192.0.2.42");
4482 auto luaconfsCopy
= g_luaconfs
.getCopy();
4483 luaconfsCopy
.dsAnchors
.clear();
4484 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4485 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4486 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384
, DNSSECKeeper::SHA384
, keys
);
4488 g_luaconfs
.setState(luaconfsCopy
);
4490 size_t queriesCount
= 0;
4492 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
, bool* chained
) {
4495 DNSName auth
= domain
;
4496 if (domain
== target
) {
4497 auth
= DNSName("powerdns.com.");
4500 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4501 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4504 if (isRootServer(ip
)) {
4505 setLWResult(res
, 0, false, false, true);
4506 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4507 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4508 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4509 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4513 if (ip
== ComboAddress("192.0.2.1:53")) {
4514 if (domain
== DNSName("com.")) {
4515 setLWResult(res
, 0, true, false, true);
4516 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4517 addRRSIG(keys
, res
->d_records
, domain
, 300);
4518 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4519 addRRSIG(keys
, res
->d_records
, domain
, 300);
4522 setLWResult(res
, 0, false, false, true);
4523 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4524 addDS(auth
, 300, res
->d_records
, keys
);
4525 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4526 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4531 if (ip
== ComboAddress("192.0.2.2:53")) {
4532 if (type
== QType::NS
) {
4533 setLWResult(res
, 0, true, false, true);
4534 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4535 addRRSIG(keys
, res
->d_records
, auth
, 300);
4536 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4537 addRRSIG(keys
, res
->d_records
, auth
, 300);
4540 setLWResult(res
, RCode::NoError
, true, false, true);
4541 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4542 addRRSIG(keys
, res
->d_records
, auth
, 300);
4550 vector
<DNSRecord
> ret
;
4551 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4552 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4553 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4554 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4555 BOOST_CHECK_EQUAL(queriesCount
, 8);
4557 /* again, to test the cache */
4559 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4560 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4561 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4562 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4563 BOOST_CHECK_EQUAL(queriesCount
, 8);
4566 BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns
) {
4567 std::unique_ptr
<SyncRes
> sr
;
4570 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4573 const DNSName
target("powerdns.com.");
4574 const ComboAddress
targetAddr("192.0.2.42");
4577 auto luaconfsCopy
= g_luaconfs
.getCopy();
4578 luaconfsCopy
.dsAnchors
.clear();
4579 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4580 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4581 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4582 g_luaconfs
.setState(luaconfsCopy
);
4584 size_t queriesCount
= 0;
4586 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
, bool* chained
) {
4589 DNSName auth
= domain
;
4590 if (domain
== target
) {
4591 auth
= DNSName("powerdns.com.");
4594 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4595 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4598 if (isRootServer(ip
)) {
4599 setLWResult(res
, 0, false, false, true);
4600 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4601 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4602 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4603 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4607 if (ip
== ComboAddress("192.0.2.1:53")) {
4608 if (domain
== DNSName("com.")) {
4609 setLWResult(res
, 0, true, false, true);
4610 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4611 addRRSIG(keys
, res
->d_records
, domain
, 300);
4612 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4613 addRRSIG(keys
, res
->d_records
, domain
, 300);
4616 setLWResult(res
, 0, false, false, true);
4617 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4618 addDS(auth
, 300, res
->d_records
, keys
);
4619 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4620 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4625 if (ip
== ComboAddress("192.0.2.2:53")) {
4626 if (type
== QType::NS
) {
4627 setLWResult(res
, 0, true, false, true);
4628 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4629 addRRSIG(keys
, res
->d_records
, auth
, 300);
4630 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4631 addRRSIG(keys
, res
->d_records
, auth
, 300);
4634 setLWResult(res
, RCode::NoError
, true, false, true);
4635 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4636 addRRSIG(keys
, res
->d_records
, auth
, 300);
4644 vector
<DNSRecord
> ret
;
4645 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4646 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4647 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4648 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4649 BOOST_CHECK_EQUAL(queriesCount
, 8);
4651 /* again, to test the cache */
4653 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4654 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4655 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4656 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4657 BOOST_CHECK_EQUAL(queriesCount
, 8);
4659 /* this time we ask for the NS that should be in the cache, to check
4660 the validation status */
4662 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4663 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4664 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4665 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4666 BOOST_CHECK_EQUAL(queriesCount
, 9);
4670 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns
) {
4671 std::unique_ptr
<SyncRes
> sr
;
4674 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4677 const DNSName
target("powerdns.com.");
4678 const ComboAddress
targetAddr("192.0.2.42");
4681 auto luaconfsCopy
= g_luaconfs
.getCopy();
4682 luaconfsCopy
.dsAnchors
.clear();
4683 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4684 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4685 g_luaconfs
.setState(luaconfsCopy
);
4687 size_t queriesCount
= 0;
4689 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
, bool* chained
) {
4692 DNSName auth
= domain
;
4693 if (domain
== target
) {
4694 auth
= DNSName("powerdns.com.");
4697 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4698 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4701 if (isRootServer(ip
)) {
4702 setLWResult(res
, 0, false, false, true);
4703 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4704 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4705 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4706 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4710 if (ip
== ComboAddress("192.0.2.1:53")) {
4711 if (domain
== DNSName("com.")) {
4712 setLWResult(res
, 0, true, false, true);
4713 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4714 addRRSIG(keys
, res
->d_records
, domain
, 300);
4715 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4716 addRRSIG(keys
, res
->d_records
, domain
, 300);
4719 setLWResult(res
, 0, false, false, true);
4720 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4722 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
4723 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4724 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4729 if (ip
== ComboAddress("192.0.2.2:53")) {
4730 if (type
== QType::NS
) {
4731 setLWResult(res
, 0, true, false, true);
4732 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4733 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4736 setLWResult(res
, RCode::NoError
, true, false, true);
4737 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4745 vector
<DNSRecord
> ret
;
4746 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4747 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4748 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4749 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4750 BOOST_CHECK_EQUAL(queriesCount
, 7);
4752 /* again, to test the cache */
4754 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4755 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4756 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4757 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4758 BOOST_CHECK_EQUAL(queriesCount
, 7);
4760 /* this time we ask for the NS that should be in the cache, to check
4761 the validation status */
4763 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4764 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4765 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4766 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4767 BOOST_CHECK_EQUAL(queriesCount
, 8);
4770 BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta
) {
4771 std::unique_ptr
<SyncRes
> sr
;
4774 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4777 const DNSName
target("powerdns.com.");
4778 const ComboAddress
targetAddr("192.0.2.42");
4781 auto luaconfsCopy
= g_luaconfs
.getCopy();
4782 luaconfsCopy
.dsAnchors
.clear();
4783 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4784 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4785 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4787 /* Add a NTA for "powerdns.com" */
4788 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4790 g_luaconfs
.setState(luaconfsCopy
);
4792 size_t queriesCount
= 0;
4794 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
, bool* chained
) {
4797 DNSName auth
= domain
;
4798 if (domain
== target
) {
4799 auth
= DNSName("powerdns.com.");
4802 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4803 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4806 if (isRootServer(ip
)) {
4807 setLWResult(res
, 0, false, false, true);
4808 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4809 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4810 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4811 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4815 if (ip
== ComboAddress("192.0.2.1:53")) {
4816 if (domain
== DNSName("com.")) {
4817 setLWResult(res
, 0, true, false, true);
4818 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4819 addRRSIG(keys
, res
->d_records
, domain
, 300);
4820 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4821 addRRSIG(keys
, res
->d_records
, domain
, 300);
4824 setLWResult(res
, 0, false, false, true);
4825 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4826 addDS(auth
, 300, res
->d_records
, keys
);
4827 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4828 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4833 if (ip
== ComboAddress("192.0.2.2:53")) {
4834 if (type
== QType::NS
) {
4835 setLWResult(res
, 0, true, false, true);
4836 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4837 addRRSIG(keys
, res
->d_records
, auth
, 300);
4838 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4839 addRRSIG(keys
, res
->d_records
, auth
, 300);
4842 setLWResult(res
, RCode::NoError
, true, false, true);
4843 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4844 addRRSIG(keys
, res
->d_records
, auth
, 300);
4852 vector
<DNSRecord
> ret
;
4853 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4854 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4855 /* Should be insecure because of the NTA */
4856 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4857 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4858 BOOST_CHECK_EQUAL(queriesCount
, 5);
4860 /* again, to test the cache */
4862 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4863 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4864 /* Should be insecure because of the NTA */
4865 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4866 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4867 BOOST_CHECK_EQUAL(queriesCount
, 5);
4870 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta
) {
4871 std::unique_ptr
<SyncRes
> sr
;
4874 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4877 const DNSName
target("powerdns.com.");
4878 const ComboAddress
targetAddr("192.0.2.42");
4881 auto luaconfsCopy
= g_luaconfs
.getCopy();
4882 luaconfsCopy
.dsAnchors
.clear();
4883 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4884 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4885 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4887 /* Add a NTA for "powerdns.com" */
4888 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4890 g_luaconfs
.setState(luaconfsCopy
);
4892 size_t queriesCount
= 0;
4894 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
, bool* chained
) {
4897 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4898 setLWResult(res
, 0, false, false, true);
4899 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4903 if (isRootServer(ip
)) {
4904 setLWResult(res
, 0, false, false, true);
4905 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4906 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4909 else if (ip
== ComboAddress("192.0.2.1:53")) {
4910 if (domain
== DNSName("com.")) {
4911 setLWResult(res
, 0, true, false, true);
4912 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4913 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4916 setLWResult(res
, 0, false, false, true);
4917 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4918 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4922 else if (ip
== ComboAddress("192.0.2.2:53")) {
4923 if (type
== QType::NS
) {
4924 setLWResult(res
, 0, true, false, true);
4925 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4926 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4929 setLWResult(res
, RCode::NoError
, true, false, true);
4930 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4939 /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
4940 vector
<DNSRecord
> ret
;
4941 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4942 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4943 /* Should be insecure because of the NTA */
4944 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4945 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4946 BOOST_CHECK_EQUAL(queriesCount
, 4);
4948 /* again, to test the cache */
4950 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4951 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4952 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4953 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4954 BOOST_CHECK_EQUAL(queriesCount
, 4);
4957 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec
) {
4958 std::unique_ptr
<SyncRes
> sr
;
4961 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4964 const DNSName
target("powerdns.com.");
4967 auto luaconfsCopy
= g_luaconfs
.getCopy();
4968 luaconfsCopy
.dsAnchors
.clear();
4969 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4970 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4971 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4973 g_luaconfs
.setState(luaconfsCopy
);
4975 size_t queriesCount
= 0;
4977 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
, bool* chained
) {
4980 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4981 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
4984 if (isRootServer(ip
)) {
4985 setLWResult(res
, 0, false, false, true);
4986 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4987 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4988 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4989 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4992 else if (ip
== ComboAddress("192.0.2.1:53")) {
4993 if (domain
== DNSName("com.")) {
4994 setLWResult(res
, 0, true, false, true);
4995 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4996 addRRSIG(keys
, res
->d_records
, domain
, 300);
4997 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4998 addRRSIG(keys
, res
->d_records
, domain
, 300);
5001 setLWResult(res
, 0, false, false, true);
5002 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5003 addDS(domain
, 300, res
->d_records
, keys
);
5004 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5005 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5009 else if (ip
== ComboAddress("192.0.2.2:53")) {
5010 if (type
== QType::NS
) {
5011 setLWResult(res
, 0, true, false, true);
5012 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5013 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5014 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5015 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5018 setLWResult(res
, 0, true, false, true);
5019 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5020 addRRSIG(keys
, res
->d_records
, domain
, 300);
5021 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
5022 addRRSIG(keys
, res
->d_records
, domain
, 300);
5031 vector
<DNSRecord
> ret
;
5032 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5033 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5034 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5035 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5036 BOOST_CHECK_EQUAL(queriesCount
, 8);
5038 /* again, to test the cache */
5040 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5041 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5042 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5043 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5044 BOOST_CHECK_EQUAL(queriesCount
, 8);
5047 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec
) {
5048 std::unique_ptr
<SyncRes
> sr
;
5051 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5054 const DNSName
target("nx.powerdns.com.");
5057 auto luaconfsCopy
= g_luaconfs
.getCopy();
5058 luaconfsCopy
.dsAnchors
.clear();
5059 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5060 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5061 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5063 g_luaconfs
.setState(luaconfsCopy
);
5065 size_t queriesCount
= 0;
5067 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
, bool* chained
) {
5070 DNSName auth
= domain
;
5071 if (domain
== target
) {
5072 auth
= DNSName("powerdns.com.");
5074 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5075 if (type
== QType::DS
&& domain
== target
) {
5076 setLWResult(res
, RCode::NXDomain
, true, false, true);
5077 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5078 addRRSIG(keys
, res
->d_records
, auth
, 300);
5079 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5080 addRRSIG(keys
, res
->d_records
, auth
, 300);
5084 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
5088 if (isRootServer(ip
)) {
5089 setLWResult(res
, 0, false, false, true);
5090 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5091 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5092 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5093 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5096 else if (ip
== ComboAddress("192.0.2.1:53")) {
5097 if (domain
== DNSName("com.")) {
5098 setLWResult(res
, 0, true, false, true);
5099 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5100 addRRSIG(keys
, res
->d_records
, domain
, 300);
5101 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5102 addRRSIG(keys
, res
->d_records
, domain
, 300);
5105 setLWResult(res
, 0, false, false, true);
5106 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5107 addDS(auth
, 300, res
->d_records
, keys
);
5108 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5109 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5113 else if (ip
== ComboAddress("192.0.2.2:53")) {
5114 if (type
== QType::NS
) {
5115 setLWResult(res
, 0, true, false, true);
5116 if (domain
== DNSName("powerdns.com.")) {
5117 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5118 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5119 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5120 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5123 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5124 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5125 addNSECRecordToLW(DNSName("nx.powerdns.com."), DNSName("nz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5126 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5130 setLWResult(res
, RCode::NXDomain
, true, false, true);
5131 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5132 addRRSIG(keys
, res
->d_records
, auth
, 300);
5133 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5134 addRRSIG(keys
, res
->d_records
, auth
, 300);
5135 /* add wildcard denial */
5136 addNSECRecordToLW(DNSName("powerdns.com."), DNSName("a.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5137 addRRSIG(keys
, res
->d_records
, auth
, 300);
5146 vector
<DNSRecord
> ret
;
5147 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5148 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
5149 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5150 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5151 BOOST_CHECK_EQUAL(queriesCount
, 9);
5153 /* again, to test the cache */
5155 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5156 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
5157 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5158 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5159 BOOST_CHECK_EQUAL(queriesCount
, 9);
5162 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard
) {
5163 std::unique_ptr
<SyncRes
> sr
;
5166 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5169 const DNSName
target("www.powerdns.com.");
5172 auto luaconfsCopy
= g_luaconfs
.getCopy();
5173 luaconfsCopy
.dsAnchors
.clear();
5174 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5175 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5176 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5178 g_luaconfs
.setState(luaconfsCopy
);
5180 size_t queriesCount
= 0;
5182 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
, bool* chained
) {
5185 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5186 if (type
== QType::DS
&& domain
== target
) {
5187 setLWResult(res
, RCode::NoError
, true, false, true);
5188 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5189 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5190 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5191 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5195 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5199 if (isRootServer(ip
)) {
5200 setLWResult(res
, 0, false, false, true);
5201 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5202 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5203 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5204 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5207 else if (ip
== ComboAddress("192.0.2.1:53")) {
5208 if (domain
== DNSName("com.")) {
5209 setLWResult(res
, 0, true, false, true);
5210 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5211 addRRSIG(keys
, res
->d_records
, domain
, 300);
5212 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5213 addRRSIG(keys
, res
->d_records
, domain
, 300);
5216 setLWResult(res
, 0, false, false, true);
5217 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5218 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5219 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5220 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5224 else if (ip
== ComboAddress("192.0.2.2:53")) {
5225 setLWResult(res
, 0, true, false, true);
5226 if (type
== QType::NS
) {
5227 if (domain
== DNSName("powerdns.com.")) {
5228 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5229 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5230 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5231 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5234 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5235 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5236 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5237 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5241 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5242 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5243 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5244 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5245 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5254 vector
<DNSRecord
> ret
;
5255 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5256 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5257 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5258 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5259 BOOST_CHECK_EQUAL(queriesCount
, 9);
5261 /* again, to test the cache */
5263 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5264 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5265 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5266 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5267 BOOST_CHECK_EQUAL(queriesCount
, 9);
5270 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_nodata_nowildcard
) {
5271 std::unique_ptr
<SyncRes
> sr
;
5274 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5277 const DNSName
target("www.com.");
5280 auto luaconfsCopy
= g_luaconfs
.getCopy();
5281 luaconfsCopy
.dsAnchors
.clear();
5282 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5283 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5285 g_luaconfs
.setState(luaconfsCopy
);
5287 size_t queriesCount
= 0;
5289 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
, bool* chained
) {
5292 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5293 if (type
== QType::DS
&& domain
== target
) {
5294 DNSName
auth("com.");
5295 setLWResult(res
, 0, true, false, true);
5297 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5298 addRRSIG(keys
, res
->d_records
, auth
, 300);
5299 /* add a NSEC denying the DS AND the existence of a cut (no NS) */
5300 addNSECRecordToLW(domain
, DNSName("z") + domain
, { QType::NSEC
}, 600, res
->d_records
);
5301 addRRSIG(keys
, res
->d_records
, auth
, 300);
5304 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5307 if (isRootServer(ip
)) {
5308 setLWResult(res
, 0, false, false, true);
5309 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5310 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5311 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5312 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5315 else if (ip
== ComboAddress("192.0.2.1:53")) {
5316 setLWResult(res
, 0, true, false, true);
5318 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5319 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5320 /* no record for this name */
5321 addNSECRecordToLW(DNSName("wwv.com."), DNSName("wwx.com."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5322 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5323 /* a wildcard matches but has no record for this type */
5324 addNSECRecordToLW(DNSName("*.com."), DNSName("com."), { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5325 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5333 vector
<DNSRecord
> ret
;
5334 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5335 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5336 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5337 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5338 BOOST_CHECK_EQUAL(queriesCount
, 6);
5340 /* again, to test the cache */
5342 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5343 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5344 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5345 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5346 BOOST_CHECK_EQUAL(queriesCount
, 6);
5349 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard
) {
5350 std::unique_ptr
<SyncRes
> sr
;
5353 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5356 const DNSName
target("www.com.");
5359 auto luaconfsCopy
= g_luaconfs
.getCopy();
5360 luaconfsCopy
.dsAnchors
.clear();
5361 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5362 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5364 g_luaconfs
.setState(luaconfsCopy
);
5366 size_t queriesCount
= 0;
5368 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
, bool* chained
) {
5371 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5372 if (type
== QType::DS
&& domain
== target
) {
5373 DNSName
auth("com.");
5374 setLWResult(res
, 0, true, false, true);
5376 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5377 addRRSIG(keys
, res
->d_records
, auth
, 300);
5378 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5379 /* first the closest encloser */
5380 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5381 addRRSIG(keys
, res
->d_records
, auth
, 300);
5382 /* then the next closer */
5383 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5384 addRRSIG(keys
, res
->d_records
, auth
, 300);
5385 /* a wildcard matches but has no record for this type */
5386 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5387 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5390 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5393 if (isRootServer(ip
)) {
5394 setLWResult(res
, 0, false, false, true);
5395 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5396 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5397 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5398 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5401 else if (ip
== ComboAddress("192.0.2.1:53")) {
5402 setLWResult(res
, 0, true, false, true);
5404 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5405 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5406 /* no record for this name */
5407 /* first the closest encloser */
5408 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5409 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5410 /* then the next closer */
5411 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5412 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5413 /* a wildcard matches but has no record for this type */
5414 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5415 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5423 vector
<DNSRecord
> ret
;
5424 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5425 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5426 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5427 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5428 BOOST_CHECK_EQUAL(queriesCount
, 6);
5430 /* again, to test the cache */
5432 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5433 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5434 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5435 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5436 BOOST_CHECK_EQUAL(queriesCount
, 6);
5439 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_too_many_iterations
) {
5440 std::unique_ptr
<SyncRes
> sr
;
5443 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5446 const DNSName
target("www.com.");
5449 auto luaconfsCopy
= g_luaconfs
.getCopy();
5450 luaconfsCopy
.dsAnchors
.clear();
5451 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5452 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5454 g_luaconfs
.setState(luaconfsCopy
);
5456 size_t queriesCount
= 0;
5458 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
, bool* chained
) {
5461 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5462 if (type
== QType::DS
&& domain
== target
) {
5463 DNSName
auth("com.");
5464 setLWResult(res
, 0, true, false, true);
5466 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5467 addRRSIG(keys
, res
->d_records
, auth
, 300);
5468 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5469 /* first the closest encloser */
5470 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5471 addRRSIG(keys
, res
->d_records
, auth
, 300);
5472 /* then the next closer */
5473 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5474 addRRSIG(keys
, res
->d_records
, auth
, 300);
5475 /* a wildcard matches but has no record for this type */
5476 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5477 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5480 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5483 if (isRootServer(ip
)) {
5484 setLWResult(res
, 0, false, false, true);
5485 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5486 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5487 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5488 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5491 else if (ip
== ComboAddress("192.0.2.1:53")) {
5492 setLWResult(res
, 0, true, false, true);
5494 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5495 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5496 /* no record for this name */
5497 /* first the closest encloser */
5498 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5499 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5500 /* then the next closer */
5501 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5502 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5503 /* a wildcard matches but has no record for this type */
5504 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5505 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5513 /* we are generating NSEC3 with more iterations than we allow, so we should go Insecure */
5514 vector
<DNSRecord
> ret
;
5515 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5516 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5517 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5518 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5519 BOOST_CHECK_EQUAL(queriesCount
, 6);
5521 /* again, to test the cache */
5523 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5524 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5525 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5526 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5527 BOOST_CHECK_EQUAL(queriesCount
, 6);
5530 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard
) {
5531 std::unique_ptr
<SyncRes
> sr
;
5534 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5537 const DNSName
target("www.sub.powerdns.com.");
5540 auto luaconfsCopy
= g_luaconfs
.getCopy();
5541 luaconfsCopy
.dsAnchors
.clear();
5542 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5543 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5544 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5546 g_luaconfs
.setState(luaconfsCopy
);
5548 size_t queriesCount
= 0;
5550 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
, bool* chained
) {
5553 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5554 if (type
== QType::DS
&& domain
.isPartOf(DNSName("sub.powerdns.com"))) {
5555 setLWResult(res
, RCode::NoError
, true, false, true);
5556 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5557 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5558 if (domain
== DNSName("sub.powerdns.com")) {
5559 addNSECRecordToLW(DNSName("sub.powerdns.com."), DNSName("sud.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5561 else if (domain
== target
) {
5562 addNSECRecordToLW(DNSName("www.sub.powerdns.com."), DNSName("wwz.sub.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5564 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5568 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5572 if (isRootServer(ip
)) {
5573 setLWResult(res
, 0, false, false, true);
5574 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5575 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5576 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5577 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5580 else if (ip
== ComboAddress("192.0.2.1:53")) {
5581 if (domain
== DNSName("com.")) {
5582 setLWResult(res
, 0, true, false, true);
5583 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5584 addRRSIG(keys
, res
->d_records
, domain
, 300);
5585 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5586 addRRSIG(keys
, res
->d_records
, domain
, 300);
5589 setLWResult(res
, 0, false, false, true);
5590 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5591 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5592 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5593 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5597 else if (ip
== ComboAddress("192.0.2.2:53")) {
5598 setLWResult(res
, 0, true, false, true);
5599 if (type
== QType::NS
) {
5600 if (domain
== DNSName("powerdns.com.")) {
5601 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5602 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5603 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5604 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5607 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5608 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5609 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5610 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5614 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5615 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5616 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5617 /* first the closest encloser */
5618 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5619 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5620 /* then the next closer */
5621 addNSEC3NarrowRecordToLW(DNSName("sub.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5622 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5631 vector
<DNSRecord
> ret
;
5632 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5633 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5634 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5635 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5636 BOOST_CHECK_EQUAL(queriesCount
, 10);
5638 /* again, to test the cache */
5640 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5641 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5642 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5643 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5644 BOOST_CHECK_EQUAL(queriesCount
, 10);
5647 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard_too_many_iterations
) {
5648 std::unique_ptr
<SyncRes
> sr
;
5651 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5654 const DNSName
target("www.powerdns.com.");
5657 auto luaconfsCopy
= g_luaconfs
.getCopy();
5658 luaconfsCopy
.dsAnchors
.clear();
5659 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5660 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5661 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5663 g_luaconfs
.setState(luaconfsCopy
);
5665 size_t queriesCount
= 0;
5667 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
, bool* chained
) {
5670 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5671 if (type
== QType::DS
&& domain
== target
) {
5672 setLWResult(res
, RCode::NoError
, true, false, true);
5673 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5674 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5675 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5676 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5680 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5684 if (isRootServer(ip
)) {
5685 setLWResult(res
, 0, false, false, true);
5686 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5687 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5688 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5689 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5692 else if (ip
== ComboAddress("192.0.2.1:53")) {
5693 if (domain
== DNSName("com.")) {
5694 setLWResult(res
, 0, true, false, true);
5695 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5696 addRRSIG(keys
, res
->d_records
, domain
, 300);
5697 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5698 addRRSIG(keys
, res
->d_records
, domain
, 300);
5701 setLWResult(res
, 0, false, false, true);
5702 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5703 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5704 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5705 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5709 else if (ip
== ComboAddress("192.0.2.2:53")) {
5710 setLWResult(res
, 0, true, false, true);
5711 if (type
== QType::NS
) {
5712 if (domain
== DNSName("powerdns.com.")) {
5713 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5714 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5715 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5716 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5719 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5720 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5721 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5722 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5726 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5727 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5728 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5729 /* first the closest encloser */
5730 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5731 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5732 /* then the next closer */
5733 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5734 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5743 /* the NSEC3 providing the denial of existence proof for the next closer has too many iterations,
5744 we should end up Insecure */
5745 vector
<DNSRecord
> ret
;
5746 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5747 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5748 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5749 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5750 BOOST_CHECK_EQUAL(queriesCount
, 9);
5752 /* again, to test the cache */
5754 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5755 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5756 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5757 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5758 BOOST_CHECK_EQUAL(queriesCount
, 9);
5761 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_missing
) {
5762 std::unique_ptr
<SyncRes
> sr
;
5765 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5768 const DNSName
target("www.powerdns.com.");
5771 auto luaconfsCopy
= g_luaconfs
.getCopy();
5772 luaconfsCopy
.dsAnchors
.clear();
5773 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5774 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5775 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5777 g_luaconfs
.setState(luaconfsCopy
);
5779 size_t queriesCount
= 0;
5781 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
, bool* chained
) {
5784 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5785 if (type
== QType::DS
&& domain
== target
) {
5786 setLWResult(res
, RCode::NoError
, true, false, true);
5787 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5788 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5789 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5790 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5794 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5798 if (isRootServer(ip
)) {
5799 setLWResult(res
, 0, false, false, true);
5800 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5801 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5802 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5803 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5806 else if (ip
== ComboAddress("192.0.2.1:53")) {
5807 if (domain
== DNSName("com.")) {
5808 setLWResult(res
, 0, true, false, true);
5809 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5810 addRRSIG(keys
, res
->d_records
, domain
, 300);
5811 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5812 addRRSIG(keys
, res
->d_records
, domain
, 300);
5815 setLWResult(res
, 0, false, false, true);
5816 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5817 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5818 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5819 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5823 else if (ip
== ComboAddress("192.0.2.2:53")) {
5824 setLWResult(res
, 0, true, false, true);
5825 if (type
== QType::NS
) {
5826 if (domain
== DNSName("powerdns.com.")) {
5827 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5828 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5829 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5830 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5833 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5834 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5835 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5836 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5840 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5841 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5850 vector
<DNSRecord
> ret
;
5851 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5852 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5853 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5854 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5855 BOOST_CHECK_EQUAL(queriesCount
, 9);
5857 /* again, to test the cache */
5859 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5860 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5861 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5862 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5863 BOOST_CHECK_EQUAL(queriesCount
, 9);
5866 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure
) {
5867 std::unique_ptr
<SyncRes
> sr
;
5870 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5873 const DNSName
target("www.powerdns.com.");
5876 auto luaconfsCopy
= g_luaconfs
.getCopy();
5877 luaconfsCopy
.dsAnchors
.clear();
5878 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5879 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5880 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5882 g_luaconfs
.setState(luaconfsCopy
);
5884 size_t queriesCount
= 0;
5885 size_t dsQueriesCount
= 0;
5887 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
, bool* chained
) {
5890 if (type
== QType::DS
) {
5891 DNSName
auth(domain
);
5895 setLWResult(res
, 0, true, false, true);
5896 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5897 addRRSIG(keys
, res
->d_records
, auth
, 300);
5900 else if (type
== QType::DNSKEY
) {
5901 setLWResult(res
, 0, true, false, true);
5902 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5903 addRRSIG(keys
, res
->d_records
, domain
, 300);
5907 if (isRootServer(ip
)) {
5908 setLWResult(res
, 0, false, false, true);
5909 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5910 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5911 /* No DS on referral, and no denial of the DS either */
5914 else if (ip
== ComboAddress("192.0.2.1:53")) {
5915 if (domain
== DNSName("com.")) {
5916 setLWResult(res
, 0, true, false, true);
5917 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5918 addRRSIG(keys
, res
->d_records
, domain
, 300);
5919 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5920 addRRSIG(keys
, res
->d_records
, domain
, 300);
5923 setLWResult(res
, 0, false, false, true);
5924 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5925 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5926 /* No DS on referral, and no denial of the DS either */
5930 else if (ip
== ComboAddress("192.0.2.2:53")) {
5931 setLWResult(res
, 0, true, false, true);
5932 if (type
== QType::NS
) {
5933 if (domain
== DNSName("powerdns.com.")) {
5934 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5935 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5936 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5937 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5940 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5941 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5942 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5943 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5947 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5948 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5958 vector
<DNSRecord
> ret
;
5959 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5960 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5961 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5962 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5963 BOOST_CHECK_EQUAL(queriesCount
, 9);
5964 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5966 /* again, to test the cache */
5968 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5969 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5970 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5971 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5972 BOOST_CHECK_EQUAL(queriesCount
, 9);
5973 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5976 BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop
) {
5977 std::unique_ptr
<SyncRes
> sr
;
5980 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5983 const DNSName
target("www.powerdns.com.");
5986 auto luaconfsCopy
= g_luaconfs
.getCopy();
5987 luaconfsCopy
.dsAnchors
.clear();
5988 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5989 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5990 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5991 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5993 g_luaconfs
.setState(luaconfsCopy
);
5995 size_t queriesCount
= 0;
5997 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
, bool* chained
) {
6000 if (type
== QType::DS
) {
6001 DNSName
auth(domain
);
6004 setLWResult(res
, 0, true, false, true);
6005 if (domain
== target
) {
6006 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
6007 addRRSIG(keys
, res
->d_records
, target
, 300);
6010 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
6011 addRRSIG(keys
, res
->d_records
, auth
, 300);
6015 else if (type
== QType::DNSKEY
) {
6016 setLWResult(res
, 0, true, false, true);
6017 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6018 addRRSIG(keys
, res
->d_records
, domain
, 300);
6022 if (isRootServer(ip
)) {
6023 setLWResult(res
, 0, false, false, true);
6024 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6025 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6026 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6027 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6030 else if (ip
== ComboAddress("192.0.2.1:53")) {
6031 if (domain
== DNSName("com.")) {
6032 setLWResult(res
, 0, true, false, true);
6033 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6034 addRRSIG(keys
, res
->d_records
, domain
, 300);
6035 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6036 addRRSIG(keys
, res
->d_records
, domain
, 300);
6039 setLWResult(res
, 0, false, false, true);
6040 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6042 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6043 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6044 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6048 else if (ip
== ComboAddress("192.0.2.2:53")) {
6049 if (type
== QType::NS
) {
6050 if (domain
== DNSName("powerdns.com.")) {
6051 setLWResult(res
, RCode::Refused
, false, false, true);
6054 setLWResult(res
, 0, true, false, true);
6055 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6056 addRRSIG(keys
, res
->d_records
, domain
, 300);
6057 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6058 addRRSIG(keys
, res
->d_records
, domain
, 300);
6062 setLWResult(res
, 0, true, false, true);
6063 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
6064 addRRSIG(keys
, res
->d_records
, DNSName("www.powerdns.com"), 300);
6074 vector
<DNSRecord
> ret
;
6075 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6076 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6077 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6078 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6079 BOOST_CHECK_EQUAL(queriesCount
, 9);
6081 /* again, to test the cache */
6083 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6084 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6085 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6086 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6087 BOOST_CHECK_EQUAL(queriesCount
, 9);
6090 BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_signed_child
) {
6091 /* check that we don't accept a signer below us */
6092 std::unique_ptr
<SyncRes
> sr
;
6095 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6098 const DNSName
target("www.powerdns.com.");
6101 auto luaconfsCopy
= g_luaconfs
.getCopy();
6102 luaconfsCopy
.dsAnchors
.clear();
6103 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6104 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6105 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6106 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6107 generateKeyMaterial(DNSName("sub.www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6109 g_luaconfs
.setState(luaconfsCopy
);
6111 size_t queriesCount
= 0;
6113 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
, bool* chained
) {
6116 if (type
== QType::DS
) {
6117 DNSName
auth(domain
);
6120 setLWResult(res
, 0, true, false, true);
6121 if (domain
== target
) {
6122 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
6123 addRRSIG(keys
, res
->d_records
, target
, 300);
6126 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
6127 addRRSIG(keys
, res
->d_records
, auth
, 300);
6131 else if (type
== QType::DNSKEY
) {
6132 setLWResult(res
, 0, true, false, true);
6133 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6134 if (domain
== DNSName("www.powerdns.com.")) {
6135 addRRSIG(keys
, res
->d_records
, DNSName("sub.www.powerdns.com."), 300);
6138 addRRSIG(keys
, res
->d_records
, domain
, 300);
6143 if (isRootServer(ip
)) {
6144 setLWResult(res
, 0, false, false, true);
6145 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6146 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6147 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6148 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6151 else if (ip
== ComboAddress("192.0.2.1:53")) {
6152 if (domain
== DNSName("com.")) {
6153 setLWResult(res
, 0, true, false, true);
6154 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6155 addRRSIG(keys
, res
->d_records
, domain
, 300);
6156 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6157 addRRSIG(keys
, res
->d_records
, domain
, 300);
6160 setLWResult(res
, 0, false, false, true);
6161 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6162 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6163 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6164 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6168 else if (ip
== ComboAddress("192.0.2.2:53")) {
6169 if (type
== QType::NS
) {
6170 setLWResult(res
, 0, true, false, true);
6171 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6172 addRRSIG(keys
, res
->d_records
, domain
, 300);
6173 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6174 addRRSIG(keys
, res
->d_records
, domain
, 300);
6177 setLWResult(res
, 0, true, false, true);
6178 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
6179 addRRSIG(keys
, res
->d_records
, domain
, 300);
6189 vector
<DNSRecord
> ret
;
6190 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6191 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6192 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6193 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6194 BOOST_CHECK_EQUAL(queriesCount
, 9);
6196 /* again, to test the cache */
6198 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6199 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6200 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6201 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6202 BOOST_CHECK_EQUAL(queriesCount
, 9);
6205 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure
) {
6206 std::unique_ptr
<SyncRes
> sr
;
6209 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6212 const DNSName
target("www.powerdns.com.");
6215 auto luaconfsCopy
= g_luaconfs
.getCopy();
6216 luaconfsCopy
.dsAnchors
.clear();
6217 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6218 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6220 g_luaconfs
.setState(luaconfsCopy
);
6222 size_t queriesCount
= 0;
6223 size_t dsQueriesCount
= 0;
6225 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
, bool* chained
) {
6228 if (type
== QType::DS
) {
6229 DNSName
auth(domain
);
6233 setLWResult(res
, 0, true, false, true);
6234 if (domain
== DNSName("com.")) {
6235 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
6238 addRecordToLW(res
, "com.", QType::SOA
, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6239 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6240 addNSECRecordToLW(domain
, DNSName("powerdnt.com."), { QType::NS
}, 600, res
->d_records
);
6242 addRRSIG(keys
, res
->d_records
, auth
, 300);
6245 else if (type
== QType::DNSKEY
) {
6246 setLWResult(res
, 0, true, false, true);
6247 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6248 addRRSIG(keys
, res
->d_records
, domain
, 300);
6252 if (isRootServer(ip
)) {
6253 setLWResult(res
, 0, false, false, true);
6254 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6255 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6256 /* No DS on referral, and no denial of the DS either */
6259 else if (ip
== ComboAddress("192.0.2.1:53")) {
6260 if (domain
== DNSName("com.")) {
6261 setLWResult(res
, 0, true, false, true);
6262 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6263 addRRSIG(keys
, res
->d_records
, domain
, 300);
6264 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6265 addRRSIG(keys
, res
->d_records
, domain
, 300);
6268 setLWResult(res
, 0, false, false, true);
6269 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6270 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6271 /* No DS on referral, and no denial of the DS either */
6275 else if (ip
== ComboAddress("192.0.2.2:53")) {
6276 setLWResult(res
, 0, true, false, true);
6277 if (type
== QType::NS
) {
6278 if (domain
== DNSName("powerdns.com.")) {
6279 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6280 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6283 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6287 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
6296 vector
<DNSRecord
> ret
;
6297 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6298 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6299 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6300 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6301 BOOST_CHECK_EQUAL(queriesCount
, 7);
6302 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6304 /* again, to test the cache */
6306 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6307 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6308 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6309 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6310 BOOST_CHECK_EQUAL(queriesCount
, 7);
6311 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6314 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec
) {
6315 std::unique_ptr
<SyncRes
> sr
;
6318 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6321 const DNSName
target("powerdns.com.");
6324 auto luaconfsCopy
= g_luaconfs
.getCopy();
6325 luaconfsCopy
.dsAnchors
.clear();
6326 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6327 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6328 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6330 g_luaconfs
.setState(luaconfsCopy
);
6332 size_t queriesCount
= 0;
6334 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
, bool* chained
) {
6337 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6338 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6341 if (isRootServer(ip
)) {
6342 setLWResult(res
, 0, false, false, true);
6343 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6344 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6345 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6346 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6349 else if (ip
== ComboAddress("192.0.2.1:53")) {
6350 if (domain
== DNSName("com.")) {
6351 setLWResult(res
, 0, true, false, true);
6352 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6353 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6354 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6357 setLWResult(res
, 0, false, false, true);
6358 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6359 addDS(domain
, 300, res
->d_records
, keys
);
6360 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6361 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6365 else if (ip
== ComboAddress("192.0.2.2:53")) {
6366 setLWResult(res
, 0, true, false, true);
6367 if (type
== QType::NS
) {
6368 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6369 addRRSIG(keys
, res
->d_records
, domain
, 300);
6372 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6373 addRRSIG(keys
, res
->d_records
, domain
, 300);
6374 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
6375 /* NO RRSIG for the NSEC record! */
6384 /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
6385 vector
<DNSRecord
> ret
;
6386 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6387 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6388 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6389 BOOST_CHECK_EQUAL(ret
.size(), 3);
6390 BOOST_CHECK_EQUAL(queriesCount
, 8);
6392 /* again, to test the cache */
6394 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6395 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6396 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6397 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6398 BOOST_CHECK_EQUAL(queriesCount
, 8);
6401 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec
) {
6402 std::unique_ptr
<SyncRes
> sr
;
6405 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6408 const DNSName
target("powerdns.com.");
6411 auto luaconfsCopy
= g_luaconfs
.getCopy();
6412 luaconfsCopy
.dsAnchors
.clear();
6413 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6414 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6415 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6417 g_luaconfs
.setState(luaconfsCopy
);
6419 size_t queriesCount
= 0;
6421 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
, bool* chained
) {
6424 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6425 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6428 if (isRootServer(ip
)) {
6429 setLWResult(res
, 0, false, false, true);
6430 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6431 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6432 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6433 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6436 else if (ip
== ComboAddress("192.0.2.1:53")) {
6437 if (domain
== DNSName("com.")) {
6438 setLWResult(res
, 0, true, false, true);
6439 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6440 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6441 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6444 setLWResult(res
, 0, false, false, true);
6445 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6446 addDS(domain
, 300, res
->d_records
, keys
);
6447 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6448 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6452 else if (ip
== ComboAddress("192.0.2.2:53")) {
6453 setLWResult(res
, 0, true, false, true);
6454 if (type
== QType::NS
) {
6455 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6456 addRRSIG(keys
, res
->d_records
, domain
, 300);
6459 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6460 addRRSIG(keys
, res
->d_records
, domain
, 300);
6462 /* NO NSEC record! */
6471 /* no NSEC record in a secure zone, should be Bogus! */
6472 vector
<DNSRecord
> ret
;
6473 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6474 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6475 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6476 BOOST_CHECK_EQUAL(ret
.size(), 2);
6477 BOOST_CHECK_EQUAL(queriesCount
, 8);
6479 /* again, to test the cache */
6481 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6482 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6483 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6484 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6485 BOOST_CHECK_EQUAL(queriesCount
, 8);
6488 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure
) {
6489 std::unique_ptr
<SyncRes
> sr
;
6492 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6495 const DNSName
target("powerdns.com.");
6496 const ComboAddress
targetAddr("192.0.2.42");
6499 auto luaconfsCopy
= g_luaconfs
.getCopy();
6500 luaconfsCopy
.dsAnchors
.clear();
6501 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6502 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6504 g_luaconfs
.setState(luaconfsCopy
);
6506 size_t queriesCount
= 0;
6508 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
, bool* chained
) {
6511 if (type
== QType::DS
) {
6512 if (domain
== target
) {
6513 setLWResult(res
, 0, false, false, true);
6514 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6515 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6516 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6519 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6522 else if (type
== QType::DNSKEY
) {
6523 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6524 setLWResult(res
, 0, true, false, true);
6525 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6526 addRRSIG(keys
, res
->d_records
, domain
, 300);
6530 setLWResult(res
, 0, false, false, true);
6531 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6536 if (isRootServer(ip
)) {
6537 setLWResult(res
, 0, false, false, true);
6538 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6539 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6540 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6541 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6544 else if (ip
== ComboAddress("192.0.2.1:53")) {
6545 if (domain
== DNSName("com.")) {
6546 setLWResult(res
, 0, true, false, true);
6547 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6548 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6549 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6552 setLWResult(res
, 0, false, false, true);
6553 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6555 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6556 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6557 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6561 else if (ip
== ComboAddress("192.0.2.2:53")) {
6562 setLWResult(res
, 0, true, false, true);
6563 if (type
== QType::NS
) {
6564 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6567 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString());
6576 vector
<DNSRecord
> ret
;
6577 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6578 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6579 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6580 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6581 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6582 /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
6583 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
6585 BOOST_CHECK_EQUAL(queriesCount
, 7);
6587 /* again, to test the cache */
6589 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6590 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6591 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6592 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6593 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6594 BOOST_CHECK_EQUAL(queriesCount
, 7);
6598 BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_ds
) {
6601 - parent is secure, zone is secure: DS should be secure
6603 std::unique_ptr
<SyncRes
> sr
;
6606 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6609 const DNSName
target("powerdns.com.");
6612 auto luaconfsCopy
= g_luaconfs
.getCopy();
6613 luaconfsCopy
.dsAnchors
.clear();
6614 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6615 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6616 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6618 g_luaconfs
.setState(luaconfsCopy
);
6620 size_t queriesCount
= 0;
6622 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
, bool* chained
) {
6625 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6626 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6629 if (isRootServer(ip
)) {
6630 setLWResult(res
, 0, false, false, true);
6631 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6632 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6633 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6634 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6642 vector
<DNSRecord
> ret
;
6643 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6644 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6645 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6646 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6647 for (const auto& record
: ret
) {
6648 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6650 BOOST_CHECK_EQUAL(queriesCount
, 4);
6652 /* again, to test the cache */
6654 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6655 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6656 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6657 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6658 for (const auto& record
: ret
) {
6659 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6661 BOOST_CHECK_EQUAL(queriesCount
, 4);
6664 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_ds
) {
6667 - parent is secure, zone is insecure: DS denial should be secure
6669 std::unique_ptr
<SyncRes
> sr
;
6672 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6675 const DNSName
target("powerdns.com.");
6678 auto luaconfsCopy
= g_luaconfs
.getCopy();
6679 luaconfsCopy
.dsAnchors
.clear();
6680 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6681 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6683 g_luaconfs
.setState(luaconfsCopy
);
6685 size_t queriesCount
= 0;
6687 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
, bool* chained
) {
6690 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6691 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6694 if (isRootServer(ip
)) {
6695 setLWResult(res
, 0, false, false, true);
6696 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6697 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6698 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6699 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6707 vector
<DNSRecord
> ret
;
6708 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6709 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6710 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6711 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6712 for (const auto& record
: ret
) {
6713 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6715 BOOST_CHECK_EQUAL(queriesCount
, 4);
6717 /* again, to test the cache */
6719 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6720 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6721 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6722 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6723 for (const auto& record
: ret
) {
6724 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6726 BOOST_CHECK_EQUAL(queriesCount
, 4);
6729 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut
) {
6730 std::unique_ptr
<SyncRes
> sr
;
6733 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6736 const DNSName
target("www.sub.powerdns.com.");
6737 const ComboAddress
targetAddr("192.0.2.42");
6740 auto luaconfsCopy
= g_luaconfs
.getCopy();
6741 luaconfsCopy
.dsAnchors
.clear();
6742 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6743 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6744 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6746 g_luaconfs
.setState(luaconfsCopy
);
6748 size_t queriesCount
= 0;
6750 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
, bool* chained
) {
6753 if (type
== QType::DS
) {
6754 if (domain
== DNSName("sub.powerdns.com.")) {
6755 setLWResult(res
, 0, false, false, true);
6756 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6757 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6758 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6759 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6762 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6763 setLWResult(res
, 0, false, false, true);
6764 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);
6768 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6771 else if (type
== QType::DNSKEY
) {
6772 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6773 setLWResult(res
, 0, true, false, true);
6774 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6775 addRRSIG(keys
, res
->d_records
, domain
, 300);
6779 setLWResult(res
, 0, false, false, true);
6780 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6785 if (isRootServer(ip
)) {
6786 setLWResult(res
, 0, false, false, true);
6787 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6788 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6789 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6790 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6793 else if (ip
== ComboAddress("192.0.2.1:53")) {
6794 if (domain
== DNSName("com.")) {
6795 setLWResult(res
, 0, true, false, true);
6796 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6797 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6798 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6801 setLWResult(res
, 0, false, false, true);
6802 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6803 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6804 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6805 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6809 else if (ip
== ComboAddress("192.0.2.2:53")) {
6810 setLWResult(res
, 0, true, false, true);
6811 if (type
== QType::NS
) {
6812 if (domain
== DNSName("www.sub.powerdns.com.")) {
6813 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);
6815 else if (domain
== DNSName("sub.powerdns.com.")) {
6816 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6818 else if (domain
== DNSName("powerdns.com.")) {
6819 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6820 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6823 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6832 vector
<DNSRecord
> ret
;
6833 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6834 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6835 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6836 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6837 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6838 BOOST_CHECK_EQUAL(queriesCount
, 9);
6840 /* again, to test the cache */
6842 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6843 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6844 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6845 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6846 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6847 BOOST_CHECK_EQUAL(queriesCount
, 9);
6850 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut
) {
6851 std::unique_ptr
<SyncRes
> sr
;
6854 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6857 const DNSName
target("www.sub.powerdns.com.");
6858 const ComboAddress
targetAddr("192.0.2.42");
6861 auto luaconfsCopy
= g_luaconfs
.getCopy();
6862 luaconfsCopy
.dsAnchors
.clear();
6863 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6864 /* No key material for .com */
6865 /* But TA for sub.powerdns.com. */
6866 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6867 luaconfsCopy
.dsAnchors
[DNSName("sub.powerdns.com.")].insert(keys
[DNSName("sub.powerdns.com.")].second
);
6868 g_luaconfs
.setState(luaconfsCopy
);
6870 size_t queriesCount
= 0;
6872 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
, bool* chained
) {
6875 if (type
== QType::DS
) {
6876 if (domain
== DNSName("www.sub.powerdns.com")) {
6877 setLWResult(res
, 0, false, false, true);
6878 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);
6879 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6880 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6881 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6884 setLWResult(res
, 0, false, false, true);
6886 if (domain
== DNSName("com.")) {
6887 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6889 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6890 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6893 setLWResult(res
, 0, false, false, true);
6894 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6899 else if (type
== QType::DNSKEY
) {
6900 if (domain
== g_rootdnsname
|| domain
== DNSName("sub.powerdns.com.")) {
6901 setLWResult(res
, 0, true, false, true);
6902 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6903 addRRSIG(keys
, res
->d_records
, domain
, 300);
6908 if (isRootServer(ip
)) {
6909 setLWResult(res
, 0, false, false, true);
6910 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6912 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6913 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6914 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6917 else if (ip
== ComboAddress("192.0.2.1:53")) {
6918 if (domain
== DNSName("com.")) {
6919 setLWResult(res
, 0, true, false, true);
6920 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6921 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6923 else if (domain
.isPartOf(DNSName("powerdns.com."))) {
6924 setLWResult(res
, 0, false, false, true);
6925 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6926 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6930 else if (ip
== ComboAddress("192.0.2.2:53")) {
6931 setLWResult(res
, 0, true, false, true);
6932 if (type
== QType::NS
) {
6933 if (domain
== DNSName("www.sub.powerdns.com.")) {
6934 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);
6935 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6936 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6937 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6939 else if (domain
== DNSName("sub.powerdns.com.")) {
6940 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6941 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6943 else if (domain
== DNSName("powerdns.com.")) {
6944 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6947 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6948 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6949 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6958 vector
<DNSRecord
> ret
;
6959 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6960 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6961 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6962 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6963 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6964 BOOST_CHECK_EQUAL(queriesCount
, 7);
6966 /* again, to test the cache */
6968 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6969 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6970 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6971 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6972 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6973 BOOST_CHECK_EQUAL(queriesCount
, 7);
6976 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata
) {
6977 std::unique_ptr
<SyncRes
> sr
;
6980 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6983 const DNSName
target("powerdns.com.");
6986 auto luaconfsCopy
= g_luaconfs
.getCopy();
6987 luaconfsCopy
.dsAnchors
.clear();
6988 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6989 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6991 g_luaconfs
.setState(luaconfsCopy
);
6993 size_t queriesCount
= 0;
6995 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
, bool* chained
) {
6998 if (type
== QType::DS
) {
6999 if (domain
== target
) {
7000 setLWResult(res
, 0, false, false, true);
7001 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7002 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
7003 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7007 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7010 else if (type
== QType::DNSKEY
) {
7011 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
7012 setLWResult(res
, 0, true, false, true);
7013 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7014 addRRSIG(keys
, res
->d_records
, domain
, 300);
7018 setLWResult(res
, 0, false, false, true);
7019 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7024 if (isRootServer(ip
)) {
7025 setLWResult(res
, 0, false, false, true);
7026 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7027 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7028 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7029 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7032 else if (ip
== ComboAddress("192.0.2.1:53")) {
7033 if (domain
== DNSName("com.")) {
7034 setLWResult(res
, 0, true, false, true);
7035 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7036 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7037 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7038 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7041 setLWResult(res
, 0, false, false, true);
7042 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7044 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
7045 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7046 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7050 else if (ip
== ComboAddress("192.0.2.2:53")) {
7051 if (type
== QType::NS
) {
7052 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7053 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7056 setLWResult(res
, 0, true, false, true);
7057 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7066 vector
<DNSRecord
> ret
;
7067 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7068 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7069 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7070 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7071 /* 4 NS (com from root, com from com, powerdns.com from com,
7072 powerdns.com from powerdns.com)
7073 2 DNSKEY (. and com., none for powerdns.com because no DS)
7076 BOOST_CHECK_EQUAL(queriesCount
, 7);
7078 /* again, to test the cache */
7080 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7081 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7082 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7083 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7084 BOOST_CHECK_EQUAL(queriesCount
, 7);
7087 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname
) {
7088 std::unique_ptr
<SyncRes
> sr
;
7091 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7094 const DNSName
target("powerdns.com.");
7095 const DNSName
targetCName("power-dns.com.");
7096 const ComboAddress
targetCNameAddr("192.0.2.42");
7099 auto luaconfsCopy
= g_luaconfs
.getCopy();
7100 luaconfsCopy
.dsAnchors
.clear();
7101 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7102 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7103 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7104 g_luaconfs
.setState(luaconfsCopy
);
7106 size_t queriesCount
= 0;
7108 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
, bool* chained
) {
7111 if (type
== QType::DS
) {
7112 if (domain
== targetCName
) {
7113 setLWResult(res
, 0, false, false, true);
7114 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7115 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7116 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7120 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7123 else if (type
== QType::DNSKEY
) {
7124 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7125 setLWResult(res
, 0, true, false, true);
7126 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7127 addRRSIG(keys
, res
->d_records
, domain
, 300);
7131 setLWResult(res
, 0, false, false, true);
7132 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7137 if (isRootServer(ip
)) {
7138 setLWResult(res
, 0, false, false, true);
7139 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7140 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7141 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7142 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7145 else if (ip
== ComboAddress("192.0.2.1:53")) {
7146 setLWResult(res
, 0, false, false, true);
7147 if (domain
== DNSName("com.")) {
7148 setLWResult(res
, 0, true, false, true);
7149 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7150 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7151 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7152 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7155 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7156 if (domain
== DNSName("powerdns.com.")) {
7157 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7159 else if (domain
== targetCName
) {
7160 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7162 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7163 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7168 else if (ip
== ComboAddress("192.0.2.2:53")) {
7169 setLWResult(res
, 0, true, false, true);
7171 if (type
== QType::NS
) {
7172 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7173 if (domain
== DNSName("powerdns.com.")) {
7174 addRRSIG(keys
, res
->d_records
, domain
, 300);
7176 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7177 if (domain
== DNSName("powerdns.com.")) {
7178 addRRSIG(keys
, res
->d_records
, domain
, 300);
7182 if (domain
== DNSName("powerdns.com.")) {
7183 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7184 addRRSIG(keys
, res
->d_records
, domain
, 300);
7186 else if (domain
== targetCName
) {
7187 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7198 vector
<DNSRecord
> ret
;
7199 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7200 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7201 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7202 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7203 BOOST_CHECK_EQUAL(queriesCount
, 11);
7205 /* again, to test the cache */
7207 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7208 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7209 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7210 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7211 BOOST_CHECK_EQUAL(queriesCount
, 11);
7214 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname_glue
) {
7215 std::unique_ptr
<SyncRes
> sr
;
7218 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7221 const DNSName
target("powerdns.com.");
7222 const DNSName
targetCName1("cname.sub.powerdns.com.");
7223 const DNSName
targetCName2("cname2.sub.powerdns.com.");
7224 const ComboAddress
targetCName2Addr("192.0.2.42");
7227 auto luaconfsCopy
= g_luaconfs
.getCopy();
7228 luaconfsCopy
.dsAnchors
.clear();
7229 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7230 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7231 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7232 g_luaconfs
.setState(luaconfsCopy
);
7234 size_t queriesCount
= 0;
7236 sr
->setAsyncCallback([target
,targetCName1
,targetCName2
,targetCName2Addr
,&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
, bool* chained
) {
7239 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7240 if (domain
== DNSName("sub.powerdns.com")) {
7241 setLWResult(res
, 0, false, false, true);
7242 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7243 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7244 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7248 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7252 if (isRootServer(ip
)) {
7253 setLWResult(res
, 0, false, false, true);
7254 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7255 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7256 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7257 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7260 else if (ip
== ComboAddress("192.0.2.1:53")) {
7261 setLWResult(res
, 0, false, false, true);
7262 if (domain
== DNSName("com.")) {
7263 setLWResult(res
, 0, true, false, true);
7264 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7265 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7266 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7267 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7270 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7271 if (domain
== DNSName("powerdns.com.")) {
7272 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7274 else if (domain
== DNSName("sub.powerdns.com")) {
7275 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7277 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7278 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7283 else if (ip
== ComboAddress("192.0.2.2:53")) {
7284 setLWResult(res
, 0, true, false, true);
7286 if (type
== QType::NS
) {
7287 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7288 if (domain
== DNSName("powerdns.com.")) {
7289 addRRSIG(keys
, res
->d_records
, domain
, 300);
7291 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7292 if (domain
== DNSName("powerdns.com.")) {
7293 addRRSIG(keys
, res
->d_records
, domain
, 300);
7297 if (domain
== DNSName("powerdns.com.")) {
7298 addRecordToLW(res
, domain
, QType::CNAME
, targetCName1
.toString());
7299 addRRSIG(keys
, res
->d_records
, domain
, 300);
7300 /* add the CNAME target as a glue, with no RRSIG since the sub zone is insecure */
7301 addRecordToLW(res
, targetCName1
, QType::CNAME
, targetCName2
.toString());
7302 addRecordToLW(res
, targetCName2
, QType::A
, targetCName2Addr
.toString());
7304 else if (domain
== targetCName1
) {
7305 addRecordToLW(res
, domain
, QType::CNAME
, targetCName2
.toString());
7307 else if (domain
== targetCName2
) {
7308 addRecordToLW(res
, domain
, QType::A
, targetCName2Addr
.toString());
7319 vector
<DNSRecord
> ret
;
7320 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7321 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7322 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7323 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7324 BOOST_CHECK_EQUAL(queriesCount
, 11);
7326 /* again, to test the cache */
7328 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7329 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7330 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7331 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7332 BOOST_CHECK_EQUAL(queriesCount
, 11);
7335 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname
) {
7336 std::unique_ptr
<SyncRes
> sr
;
7339 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7342 const DNSName
target("power-dns.com.");
7343 const DNSName
targetCName("powerdns.com.");
7344 const ComboAddress
targetCNameAddr("192.0.2.42");
7347 auto luaconfsCopy
= g_luaconfs
.getCopy();
7348 luaconfsCopy
.dsAnchors
.clear();
7349 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7350 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7351 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7352 g_luaconfs
.setState(luaconfsCopy
);
7354 size_t queriesCount
= 0;
7356 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
, bool* chained
) {
7359 if (type
== QType::DS
) {
7360 if (domain
== DNSName("power-dns.com.")) {
7361 setLWResult(res
, 0, false, false, true);
7362 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7363 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7364 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7368 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7371 else if (type
== QType::DNSKEY
) {
7372 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7373 setLWResult(res
, 0, true, false, true);
7374 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7375 addRRSIG(keys
, res
->d_records
, domain
, 300);
7379 setLWResult(res
, 0, false, false, true);
7380 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7385 if (isRootServer(ip
)) {
7386 setLWResult(res
, 0, false, false, true);
7387 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7388 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7389 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7390 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7393 else if (ip
== ComboAddress("192.0.2.1:53")) {
7394 if (domain
== DNSName("com.")) {
7395 setLWResult(res
, 0, true, false, true);
7396 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7397 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7398 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7399 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7401 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7402 setLWResult(res
, 0, false, false, true);
7403 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7404 if (domain
== targetCName
) {
7405 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7407 else if (domain
== target
) {
7408 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7410 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7411 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7415 else if (ip
== ComboAddress("192.0.2.2:53")) {
7416 setLWResult(res
, 0, true, false, true);
7417 if (type
== QType::NS
) {
7418 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7419 if (domain
== DNSName("powerdns.com.")) {
7420 addRRSIG(keys
, res
->d_records
, domain
, 300);
7422 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7423 if (domain
== DNSName("powerdns.com.")) {
7424 addRRSIG(keys
, res
->d_records
, domain
, 300);
7428 if (domain
== target
) {
7429 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7431 else if (domain
== targetCName
) {
7432 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7433 addRRSIG(keys
, res
->d_records
, domain
, 300);
7443 vector
<DNSRecord
> ret
;
7444 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7445 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7446 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7447 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7448 BOOST_CHECK_EQUAL(queriesCount
, 11);
7450 /* again, to test the cache */
7452 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7453 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7454 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7455 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7456 BOOST_CHECK_EQUAL(queriesCount
, 11);
7459 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname
) {
7460 std::unique_ptr
<SyncRes
> sr
;
7463 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7466 const DNSName
target("power-dns.com.");
7467 const DNSName
targetCName("powerdns.com.");
7468 const ComboAddress
targetCNameAddr("192.0.2.42");
7471 auto luaconfsCopy
= g_luaconfs
.getCopy();
7472 luaconfsCopy
.dsAnchors
.clear();
7473 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7474 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7475 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7476 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7477 g_luaconfs
.setState(luaconfsCopy
);
7479 size_t queriesCount
= 0;
7481 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
, bool* chained
) {
7484 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7485 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7488 if (isRootServer(ip
)) {
7489 setLWResult(res
, 0, false, false, true);
7490 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7491 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7492 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7493 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7496 else if (ip
== ComboAddress("192.0.2.1:53")) {
7497 if (domain
== DNSName("com.")) {
7498 setLWResult(res
, 0, true, false, true);
7499 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7500 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7501 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7502 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7504 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7505 setLWResult(res
, 0, false, false, true);
7506 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7507 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7508 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7509 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7513 else if (ip
== ComboAddress("192.0.2.2:53")) {
7514 setLWResult(res
, 0, true, false, true);
7515 if (type
== QType::NS
) {
7516 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7517 addRRSIG(keys
, res
->d_records
, domain
, 300);
7518 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7519 addRRSIG(keys
, res
->d_records
, domain
, 300);
7522 if (domain
== target
) {
7523 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7524 /* No RRSIG, leading to bogus */
7526 else if (domain
== targetCName
) {
7527 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7528 addRRSIG(keys
, res
->d_records
, domain
, 300);
7538 vector
<DNSRecord
> ret
;
7539 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7540 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7541 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7542 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7543 BOOST_CHECK_EQUAL(queriesCount
, 11);
7545 /* again, to test the cache */
7547 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7548 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7549 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7550 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7551 BOOST_CHECK_EQUAL(queriesCount
, 11);
7554 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname
) {
7555 std::unique_ptr
<SyncRes
> sr
;
7558 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7561 const DNSName
target("power-dns.com.");
7562 const DNSName
targetCName("powerdns.com.");
7563 const ComboAddress
targetCNameAddr("192.0.2.42");
7566 auto luaconfsCopy
= g_luaconfs
.getCopy();
7567 luaconfsCopy
.dsAnchors
.clear();
7568 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7569 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7570 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7571 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7572 g_luaconfs
.setState(luaconfsCopy
);
7574 size_t queriesCount
= 0;
7576 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
, bool* chained
) {
7579 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7580 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7583 if (isRootServer(ip
)) {
7584 setLWResult(res
, 0, false, false, true);
7585 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7586 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7587 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7588 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7591 else if (ip
== ComboAddress("192.0.2.1:53")) {
7592 if (domain
== DNSName("com.")) {
7593 setLWResult(res
, 0, true, false, true);
7594 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7595 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7596 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7597 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7599 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7600 setLWResult(res
, 0, false, false, true);
7601 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7602 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7603 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7604 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7608 else if (ip
== ComboAddress("192.0.2.2:53")) {
7609 setLWResult(res
, 0, true, false, true);
7610 if (type
== QType::NS
) {
7611 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7612 addRRSIG(keys
, res
->d_records
, domain
, 300);
7613 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7614 addRRSIG(keys
, res
->d_records
, domain
, 300);
7617 if (domain
== target
) {
7618 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7619 addRRSIG(keys
, res
->d_records
, domain
, 300);
7621 else if (domain
== targetCName
) {
7622 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7623 /* No RRSIG, leading to bogus */
7633 vector
<DNSRecord
> ret
;
7634 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7635 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7636 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7637 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7638 BOOST_CHECK_EQUAL(queriesCount
, 11);
7640 /* again, to test the cache */
7642 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7643 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7644 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7645 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7646 BOOST_CHECK_EQUAL(queriesCount
, 11);
7649 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname
) {
7650 std::unique_ptr
<SyncRes
> sr
;
7653 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7656 const DNSName
target("power-dns.com.");
7657 const DNSName
targetCName("powerdns.com.");
7658 const ComboAddress
targetCNameAddr("192.0.2.42");
7661 auto luaconfsCopy
= g_luaconfs
.getCopy();
7662 luaconfsCopy
.dsAnchors
.clear();
7663 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7664 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7665 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7666 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7667 g_luaconfs
.setState(luaconfsCopy
);
7669 size_t queriesCount
= 0;
7671 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
, bool* chained
) {
7674 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7675 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7678 if (isRootServer(ip
)) {
7679 setLWResult(res
, 0, false, false, true);
7680 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7681 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7682 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7683 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7686 else if (ip
== ComboAddress("192.0.2.1:53")) {
7687 if (domain
== DNSName("com.")) {
7688 setLWResult(res
, 0, true, false, true);
7689 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7690 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7691 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7692 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7694 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7695 setLWResult(res
, 0, false, false, true);
7696 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7697 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7698 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7699 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7703 else if (ip
== ComboAddress("192.0.2.2:53")) {
7704 setLWResult(res
, 0, true, false, true);
7705 if (type
== QType::NS
) {
7706 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7707 addRRSIG(keys
, res
->d_records
, domain
, 300);
7708 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7709 addRRSIG(keys
, res
->d_records
, domain
, 300);
7712 if (domain
== target
) {
7713 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7714 addRRSIG(keys
, res
->d_records
, domain
, 300);
7716 else if (domain
== targetCName
) {
7717 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7718 addRRSIG(keys
, res
->d_records
, domain
, 300);
7728 vector
<DNSRecord
> ret
;
7729 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7730 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7731 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7732 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7733 BOOST_CHECK_EQUAL(queriesCount
, 12);
7735 /* again, to test the cache */
7737 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7738 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7739 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7740 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7741 BOOST_CHECK_EQUAL(queriesCount
, 12);
7744 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname
) {
7745 std::unique_ptr
<SyncRes
> sr
;
7748 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7751 const DNSName
target("powerdns.com.");
7752 const DNSName
targetCName("power-dns.com.");
7753 const ComboAddress
targetCNameAddr("192.0.2.42");
7756 auto luaconfsCopy
= g_luaconfs
.getCopy();
7757 luaconfsCopy
.dsAnchors
.clear();
7758 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7759 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7760 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7761 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7762 g_luaconfs
.setState(luaconfsCopy
);
7764 size_t queriesCount
= 0;
7766 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
, bool* chained
) {
7769 if (type
== QType::DS
) {
7770 if (domain
== DNSName("power-dns.com.")) {
7771 setLWResult(res
, 0, false, false, true);
7772 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7773 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7774 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7778 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7781 else if (type
== QType::DNSKEY
) {
7782 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7783 setLWResult(res
, 0, true, false, true);
7784 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7785 addRRSIG(keys
, res
->d_records
, domain
, 300);
7789 setLWResult(res
, 0, false, false, true);
7790 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7795 if (isRootServer(ip
)) {
7796 setLWResult(res
, 0, false, false, true);
7797 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7798 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7799 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7800 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7803 else if (ip
== ComboAddress("192.0.2.1:53")) {
7804 if (domain
== DNSName("com.")) {
7805 setLWResult(res
, 0, true, false, true);
7806 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7807 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7808 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7809 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7811 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7812 setLWResult(res
, 0, false, false, true);
7813 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7814 if (domain
== DNSName("powerdns.com.")) {
7815 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7817 else if (domain
== targetCName
) {
7818 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7820 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7821 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7825 else if (ip
== ComboAddress("192.0.2.2:53")) {
7826 setLWResult(res
, 0, true, false, true);
7827 if (type
== QType::NS
) {
7828 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7829 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7832 if (domain
== DNSName("powerdns.com.")) {
7833 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7834 /* No RRSIG -> Bogus */
7836 else if (domain
== targetCName
) {
7837 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7847 vector
<DNSRecord
> ret
;
7848 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7849 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7850 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7851 /* no RRSIG to show */
7852 BOOST_CHECK_EQUAL(ret
.size(), 2);
7853 BOOST_CHECK_EQUAL(queriesCount
, 10);
7855 /* again, to test the cache */
7857 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7858 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7859 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7860 BOOST_CHECK_EQUAL(ret
.size(), 2);
7861 BOOST_CHECK_EQUAL(queriesCount
, 10);
7864 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta
) {
7865 std::unique_ptr
<SyncRes
> sr
;
7868 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7871 const DNSName
target("powerdns.com.");
7872 const ComboAddress
targetAddr("192.0.2.42");
7875 auto luaconfsCopy
= g_luaconfs
.getCopy();
7876 luaconfsCopy
.dsAnchors
.clear();
7877 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7878 /* No key material for .com */
7879 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7880 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7881 g_luaconfs
.setState(luaconfsCopy
);
7883 size_t queriesCount
= 0;
7885 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
, bool* chained
) {
7888 if (type
== QType::DNSKEY
) {
7889 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7890 setLWResult(res
, 0, true, false, true);
7891 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7892 addRRSIG(keys
, res
->d_records
, domain
, 300);
7895 else if (domain
== DNSName("com.")) {
7896 setLWResult(res
, 0, false, false, true);
7897 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7902 if (isRootServer(ip
)) {
7903 setLWResult(res
, 0, false, false, true);
7904 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7905 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7906 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7907 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7910 else if (ip
== ComboAddress("192.0.2.1:53")) {
7911 if (target
== domain
) {
7912 setLWResult(res
, 0, false, false, true);
7913 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7914 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7916 else if (domain
== DNSName("com.")) {
7917 setLWResult(res
, 0, true, false, true);
7918 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7919 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7923 else if (ip
== ComboAddress("192.0.2.2:53")) {
7924 setLWResult(res
, 0, true, false, true);
7925 if (type
== QType::NS
) {
7926 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7929 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7931 addRRSIG(keys
, res
->d_records
, domain
, 300);
7939 vector
<DNSRecord
> ret
;
7940 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7941 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7942 /* should be insecure but we have a TA for powerdns.com. */
7943 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7944 /* We got a RRSIG */
7945 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7946 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7947 BOOST_CHECK_EQUAL(queriesCount
, 5);
7949 /* again, to test the cache */
7951 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7952 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7953 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7954 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7955 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7956 BOOST_CHECK_EQUAL(queriesCount
, 5);
7959 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig
) {
7960 std::unique_ptr
<SyncRes
> sr
;
7963 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7966 const DNSName
target("powerdns.com.");
7967 const ComboAddress
targetAddr("192.0.2.42");
7970 auto luaconfsCopy
= g_luaconfs
.getCopy();
7971 luaconfsCopy
.dsAnchors
.clear();
7972 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7973 /* No key material for .com */
7974 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7975 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7976 g_luaconfs
.setState(luaconfsCopy
);
7978 size_t queriesCount
= 0;
7980 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
, bool* chained
) {
7983 if (type
== QType::DNSKEY
) {
7984 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7985 setLWResult(res
, 0, true, false, true);
7986 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7987 addRRSIG(keys
, res
->d_records
, domain
, 300);
7990 else if (domain
== DNSName("com.")) {
7991 setLWResult(res
, 0, false, false, true);
7992 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7997 if (target
.isPartOf(domain
) && isRootServer(ip
)) {
7998 setLWResult(res
, 0, false, false, true);
7999 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
8000 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
8001 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8002 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
8005 else if (ip
== ComboAddress("192.0.2.1:53")) {
8006 if (target
== domain
) {
8007 setLWResult(res
, 0, false, false, true);
8008 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
8009 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
8011 else if (domain
== DNSName("com.")) {
8012 setLWResult(res
, 0, true, false, true);
8013 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
8014 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
8018 else if (domain
== target
&& ip
== ComboAddress("192.0.2.2:53")) {
8019 setLWResult(res
, 0, true, false, true);
8020 if (type
== QType::NS
) {
8021 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
8024 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
8026 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
8034 vector
<DNSRecord
> ret
;
8035 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8036 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8037 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
8038 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8040 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8041 BOOST_CHECK(ret
[0].d_type
== QType::A
);
8042 BOOST_CHECK_EQUAL(queriesCount
, 4);
8044 /* again, to test the cache */
8046 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8047 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8048 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8049 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8050 BOOST_CHECK(ret
[0].d_type
== QType::A
);
8051 BOOST_CHECK_EQUAL(queriesCount
, 4);
8054 BOOST_AUTO_TEST_CASE(test_dnssec_nta
) {
8055 std::unique_ptr
<SyncRes
> sr
;
8058 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8061 const DNSName
target(".");
8064 auto luaconfsCopy
= g_luaconfs
.getCopy();
8065 luaconfsCopy
.dsAnchors
.clear();
8066 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8067 /* Add a NTA for "." */
8068 luaconfsCopy
.negAnchors
[g_rootdnsname
] = "NTA for Root";
8069 g_luaconfs
.setState(luaconfsCopy
);
8071 size_t queriesCount
= 0;
8073 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
, bool* chained
) {
8076 if (domain
== target
&& type
== QType::NS
) {
8078 setLWResult(res
, 0, true, false, true);
8079 char addr
[] = "a.root-servers.net.";
8080 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
8082 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
8085 addRRSIG(keys
, res
->d_records
, domain
, 300);
8087 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
8088 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
8091 } else if (domain
== target
&& type
== QType::DNSKEY
) {
8093 setLWResult(res
, 0, true, false, true);
8103 vector
<DNSRecord
> ret
;
8104 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8105 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8106 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8107 /* 13 NS + 1 RRSIG */
8108 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
8109 BOOST_CHECK_EQUAL(queriesCount
, 1);
8111 /* again, to test the cache */
8113 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8114 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8115 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8116 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
8117 BOOST_CHECK_EQUAL(queriesCount
, 1);
8120 BOOST_AUTO_TEST_CASE(test_dnssec_no_ta
) {
8121 std::unique_ptr
<SyncRes
> sr
;
8124 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8127 const DNSName
target(".");
8130 /* Remove the root DS */
8131 auto luaconfsCopy
= g_luaconfs
.getCopy();
8132 luaconfsCopy
.dsAnchors
.clear();
8133 g_luaconfs
.setState(luaconfsCopy
);
8135 size_t queriesCount
= 0;
8137 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
, bool* chained
) {
8140 if (domain
== target
&& type
== QType::NS
) {
8142 setLWResult(res
, 0, true, false, true);
8143 char addr
[] = "a.root-servers.net.";
8144 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
8146 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
8149 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
8150 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
8158 vector
<DNSRecord
> ret
;
8159 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8160 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8161 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8162 /* 13 NS + 0 RRSIG */
8163 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
8164 BOOST_CHECK_EQUAL(queriesCount
, 1);
8166 /* again, to test the cache */
8168 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8169 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8170 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8171 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
8172 BOOST_CHECK_EQUAL(queriesCount
, 1);
8175 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata
) {
8176 std::unique_ptr
<SyncRes
> sr
;
8179 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8182 const DNSName
target("powerdns.com.");
8185 auto luaconfsCopy
= g_luaconfs
.getCopy();
8186 luaconfsCopy
.dsAnchors
.clear();
8187 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8188 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8189 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8190 g_luaconfs
.setState(luaconfsCopy
);
8192 size_t queriesCount
= 0;
8194 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
, bool* chained
) {
8197 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8198 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
8202 setLWResult(res
, 0, true, false, true);
8209 vector
<DNSRecord
> ret
;
8210 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8211 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8212 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8213 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
8214 /* com|NS, powerdns.com|NS, powerdns.com|A */
8215 BOOST_CHECK_EQUAL(queriesCount
, 3);
8217 /* again, to test the cache */
8219 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8220 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8221 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8222 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
8223 /* we don't store empty results */
8224 BOOST_CHECK_EQUAL(queriesCount
, 4);
8227 BOOST_AUTO_TEST_CASE(test_nsec_denial_nowrap
) {
8231 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8233 vector
<DNSRecord
> records
;
8235 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8236 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8240 a.example.org. -> d.example.org. denies the existence of b.example.org.
8242 addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8243 recordContents
.push_back(records
.at(0).d_content
);
8244 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8245 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8248 ContentSigPair pair
;
8249 pair
.records
= recordContents
;
8250 pair
.signatures
= signatureContents
;
8252 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
8254 /* add wildcard denial */
8255 recordContents
.clear();
8256 signatureContents
.clear();
8257 addNSECRecordToLW(DNSName("example.org."), DNSName("+.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8258 recordContents
.push_back(records
.at(0).d_content
);
8259 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8260 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8263 pair
.records
= recordContents
;
8264 pair
.signatures
= signatureContents
;
8265 denialMap
[std::make_pair(DNSName("example.org."), QType::NSEC
)] = pair
;
8267 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
8268 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8270 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
8271 /* let's check that d.example.org. is not denied by this proof */
8272 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8275 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_1
) {
8279 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8281 vector
<DNSRecord
> records
;
8283 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8284 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8287 Wrap case 1 test case:
8288 z.example.org. -> b.example.org. denies the existence of a.example.org.
8290 addNSECRecordToLW(DNSName("z.example.org."), DNSName("b.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8291 recordContents
.push_back(records
.at(0).d_content
);
8292 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8293 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8296 ContentSigPair pair
;
8297 pair
.records
= recordContents
;
8298 pair
.signatures
= signatureContents
;
8300 denialMap
[std::make_pair(DNSName("z.example.org."), QType::NSEC
)] = pair
;
8302 dState denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
8303 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8305 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
8306 /* let's check that d.example.org. is not denied by this proof */
8307 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8310 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_2
) {
8314 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8316 vector
<DNSRecord
> records
;
8318 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8319 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8322 Wrap case 2 test case:
8323 y.example.org. -> a.example.org. denies the existence of z.example.org.
8325 addNSECRecordToLW(DNSName("y.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8326 recordContents
.push_back(records
.at(0).d_content
);
8327 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8328 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8331 ContentSigPair pair
;
8332 pair
.records
= recordContents
;
8333 pair
.signatures
= signatureContents
;
8335 denialMap
[std::make_pair(DNSName("y.example.org."), QType::NSEC
)] = pair
;
8337 dState denialState
= getDenial(denialMap
, DNSName("z.example.org."), QType::A
, false, false);
8338 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8340 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
8341 /* let's check that d.example.org. is not denied by this proof */
8342 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8345 BOOST_AUTO_TEST_CASE(test_nsec_denial_only_one_nsec
) {
8349 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8351 vector
<DNSRecord
> records
;
8353 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8354 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8357 Only one NSEC in the whole zone test case:
8358 a.example.org. -> a.example.org. denies the existence of b.example.org.
8360 addNSECRecordToLW(DNSName("a.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8361 recordContents
.push_back(records
.at(0).d_content
);
8362 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8363 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8366 ContentSigPair pair
;
8367 pair
.records
= recordContents
;
8368 pair
.signatures
= signatureContents
;
8370 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
8372 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
8373 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8375 denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
8376 /* let's check that d.example.org. is not denied by this proof */
8377 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8380 BOOST_AUTO_TEST_CASE(test_nsec_root_nxd_denial
) {
8384 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8386 vector
<DNSRecord
> records
;
8388 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8389 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8392 The RRSIG from "." denies the existence of anything between a. and c.,
8395 addNSECRecordToLW(DNSName("a."), DNSName("c."), { QType::NS
}, 600, records
);
8396 recordContents
.push_back(records
.at(0).d_content
);
8397 addRRSIG(keys
, records
, DNSName("."), 300);
8398 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8401 ContentSigPair pair
;
8402 pair
.records
= recordContents
;
8403 pair
.signatures
= signatureContents
;
8405 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8407 /* add wildcard denial */
8408 recordContents
.clear();
8409 signatureContents
.clear();
8410 addNSECRecordToLW(DNSName("."), DNSName("+"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8411 recordContents
.push_back(records
.at(0).d_content
);
8412 addRRSIG(keys
, records
, DNSName("."), 300);
8413 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8416 pair
.records
= recordContents
;
8417 pair
.signatures
= signatureContents
;
8418 denialMap
[std::make_pair(DNSName("."), QType::NSEC
)] = pair
;
8420 dState denialState
= getDenial(denialMap
, DNSName("b."), QType::A
, false, false);
8421 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8424 BOOST_AUTO_TEST_CASE(test_nsec_ancestor_nxqtype_denial
) {
8428 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8430 vector
<DNSRecord
> records
;
8432 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8433 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8436 The RRSIG from "." denies the existence of any type except NS at a.
8437 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8438 signer field that is shorter than the owner name of the NSEC RR) it can't
8439 be used to deny anything except the whole name or a DS.
8441 addNSECRecordToLW(DNSName("a."), DNSName("b."), { QType::NS
}, 600, records
);
8442 recordContents
.push_back(records
.at(0).d_content
);
8443 addRRSIG(keys
, records
, DNSName("."), 300);
8444 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8447 ContentSigPair pair
;
8448 pair
.records
= recordContents
;
8449 pair
.signatures
= signatureContents
;
8451 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8453 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8454 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8455 nonexistence of any RRs below that zone cut, which include all RRs at
8456 that (original) owner name other than DS RRs, and all RRs below that
8457 owner name regardless of type.
8460 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, false);
8461 /* no data means the qname/qtype is not denied, because an ancestor
8462 delegation NSEC can only deny the DS */
8463 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8465 /* it can not be used to deny any RRs below that owner name either */
8466 denialState
= getDenial(denialMap
, DNSName("sub.a."), QType::A
, false, false);
8467 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8469 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8470 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8473 BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial
) {
8477 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8479 vector
<DNSRecord
> records
;
8481 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8482 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8485 * RFC 5155 section 8.9:
8486 * If there is an NSEC3 RR present in the response that matches the
8487 * delegation name, then the validator MUST ensure that the NS bit is
8488 * set and that the DS bit is not set in the Type Bit Maps field of the
8492 The RRSIG from "." denies the existence of any type at a.
8493 NS should be set if it was proving an insecure delegation, let's check that
8494 we correctly detect that it's not.
8496 addNSECRecordToLW(DNSName("a."), DNSName("b."), { }, 600, records
);
8497 recordContents
.push_back(records
.at(0).d_content
);
8498 addRRSIG(keys
, records
, DNSName("."), 300);
8499 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8502 ContentSigPair pair
;
8503 pair
.records
= recordContents
;
8504 pair
.signatures
= signatureContents
;
8506 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8508 /* Insecure because the NS is not set, so while it does
8509 denies the DS, it can't prove an insecure delegation */
8510 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8511 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8514 BOOST_AUTO_TEST_CASE(test_nsec_nxqtype_cname
) {
8518 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8520 vector
<DNSRecord
> records
;
8522 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8523 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8525 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::CNAME
}, 600, records
);
8526 recordContents
.push_back(records
.at(0).d_content
);
8527 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8528 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8531 ContentSigPair pair
;
8532 pair
.records
= recordContents
;
8533 pair
.signatures
= signatureContents
;
8535 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8537 /* this NSEC is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8538 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, true, true);
8539 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8542 BOOST_AUTO_TEST_CASE(test_nsec3_nxqtype_cname
) {
8546 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8548 vector
<DNSRecord
> records
;
8550 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8551 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8553 addNSEC3UnhashedRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::CNAME
}, 600, records
);
8554 recordContents
.push_back(records
.at(0).d_content
);
8555 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8556 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8558 ContentSigPair pair
;
8559 pair
.records
= recordContents
;
8560 pair
.signatures
= signatureContents
;
8562 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8565 /* this NSEC3 is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8566 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, false, true);
8567 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8570 BOOST_AUTO_TEST_CASE(test_nsec_nxdomain_denial_missing_wildcard
) {
8574 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8576 vector
<DNSRecord
> records
;
8578 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8579 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8581 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("d.powerdns.com"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8582 recordContents
.push_back(records
.at(0).d_content
);
8583 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8584 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8587 ContentSigPair pair
;
8588 pair
.records
= recordContents
;
8589 pair
.signatures
= signatureContents
;
8591 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8593 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8594 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8597 BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard
) {
8601 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8603 vector
<DNSRecord
> records
;
8605 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8606 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8608 addNSEC3NarrowRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8609 recordContents
.push_back(records
.at(0).d_content
);
8610 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8611 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8613 ContentSigPair pair
;
8614 pair
.records
= recordContents
;
8615 pair
.signatures
= signatureContents
;
8617 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8619 /* Add NSEC3 for the closest encloser */
8620 recordContents
.clear();
8621 signatureContents
.clear();
8623 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8624 recordContents
.push_back(records
.at(0).d_content
);
8625 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8626 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8628 pair
.records
= recordContents
;
8629 pair
.signatures
= signatureContents
;
8630 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8632 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8633 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8636 BOOST_AUTO_TEST_CASE(test_nsec_ent_denial
) {
8640 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8642 vector
<DNSRecord
> records
;
8644 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8645 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8647 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::A
}, 600, records
);
8648 recordContents
.push_back(records
.at(0).d_content
);
8649 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8650 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8653 ContentSigPair pair
;
8654 pair
.records
= recordContents
;
8655 pair
.signatures
= signatureContents
;
8657 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8659 /* this NSEC is valid to prove a NXQTYPE at c.powerdns.com because it proves that
8661 dState denialState
= getDenial(denialMap
, DNSName("c.powerdns.com."), QType::AAAA
, true, true);
8662 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8664 /* this NSEC is not valid to prove a NXQTYPE at b.powerdns.com,
8665 it could prove a NXDOMAIN if it had an additional wildcard denial */
8666 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::AAAA
, true, true);
8667 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8669 /* this NSEC is not valid to prove a NXQTYPE for QType::A at a.c.powerdns.com either */
8670 denialState
= getDenial(denialMap
, DNSName("a.c.powerdns.com."), QType::A
, true, true);
8671 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8673 /* if we add the wildcard denial proof, we should get a NXDOMAIN proof for b.powerdns.com */
8674 recordContents
.clear();
8675 signatureContents
.clear();
8676 addNSECRecordToLW(DNSName(").powerdns.com."), DNSName("+.powerdns.com."), { }, 600, records
);
8677 recordContents
.push_back(records
.at(0).d_content
);
8678 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8679 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8681 pair
.records
= recordContents
;
8682 pair
.signatures
= signatureContents
;
8683 denialMap
[std::make_pair(DNSName(").powerdns.com."), QType::NSEC
)] = pair
;
8685 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, true, false);
8686 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8689 BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial
) {
8693 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8695 vector
<DNSRecord
> records
;
8697 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8698 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8701 The RRSIG from "." denies the existence of any type except NS at a.
8702 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8703 signer field that is shorter than the owner name of the NSEC RR) it can't
8704 be used to deny anything except the whole name or a DS.
8706 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::NS
}, 600, records
);
8707 recordContents
.push_back(records
.at(0).d_content
);
8708 addRRSIG(keys
, records
, DNSName("."), 300);
8709 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8711 ContentSigPair pair
;
8712 pair
.records
= recordContents
;
8713 pair
.signatures
= signatureContents
;
8715 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8718 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8719 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8720 nonexistence of any RRs below that zone cut, which include all RRs at
8721 that (original) owner name other than DS RRs, and all RRs below that
8722 owner name regardless of type.
8725 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8726 /* no data means the qname/qtype is not denied, because an ancestor
8727 delegation NSEC3 can only deny the DS */
8728 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8730 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8731 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8733 /* it can not be used to deny any RRs below that owner name either */
8734 /* Add NSEC3 for the next closer */
8735 recordContents
.clear();
8736 signatureContents
.clear();
8738 addNSEC3NarrowRecordToLW(DNSName("sub.a."), DNSName("."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC3
}, 600, records
);
8739 recordContents
.push_back(records
.at(0).d_content
);
8740 addRRSIG(keys
, records
, DNSName("."), 300);
8741 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8743 pair
.records
= recordContents
;
8744 pair
.signatures
= signatureContents
;
8745 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8747 /* add wildcard denial */
8748 recordContents
.clear();
8749 signatureContents
.clear();
8751 addNSEC3NarrowRecordToLW(DNSName("*.a."), DNSName("."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC3
}, 600, records
);
8752 recordContents
.push_back(records
.at(0).d_content
);
8753 addRRSIG(keys
, records
, DNSName("."), 300);
8754 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8756 pair
.records
= recordContents
;
8757 pair
.signatures
= signatureContents
;
8758 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8760 denialState
= getDenial(denialMap
, DNSName("sub.a."), QType::A
, false, true);
8761 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8764 BOOST_AUTO_TEST_CASE(test_nsec3_denial_too_many_iterations
) {
8768 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8770 vector
<DNSRecord
> records
;
8772 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8773 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8775 /* adding a NSEC3 with more iterations that we support */
8776 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::AAAA
}, 600, records
, g_maxNSEC3Iterations
+ 100);
8777 recordContents
.push_back(records
.at(0).d_content
);
8778 addRRSIG(keys
, records
, DNSName("."), 300);
8779 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8781 ContentSigPair pair
;
8782 pair
.records
= recordContents
;
8783 pair
.signatures
= signatureContents
;
8785 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8788 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8789 /* since we refuse to compute more than g_maxNSEC3Iterations iterations, it should be Insecure */
8790 BOOST_CHECK_EQUAL(denialState
, INSECURE
);
8793 BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial
) {
8797 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8799 vector
<DNSRecord
> records
;
8801 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8802 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8805 * RFC 5155 section 8.9:
8806 * If there is an NSEC3 RR present in the response that matches the
8807 * delegation name, then the validator MUST ensure that the NS bit is
8808 * set and that the DS bit is not set in the Type Bit Maps field of the
8812 The RRSIG from "." denies the existence of any type at a.
8813 NS should be set if it was proving an insecure delegation, let's check that
8814 we correctly detect that it's not.
8816 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { }, 600, records
);
8817 recordContents
.push_back(records
.at(0).d_content
);
8818 addRRSIG(keys
, records
, DNSName("."), 300);
8819 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8821 ContentSigPair pair
;
8822 pair
.records
= recordContents
;
8823 pair
.signatures
= signatureContents
;
8825 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8828 /* Insecure because the NS is not set, so while it does
8829 denies the DS, it can't prove an insecure delegation */
8830 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8831 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8834 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_negcache_validity
) {
8835 std::unique_ptr
<SyncRes
> sr
;
8838 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8841 const DNSName
target("com.");
8844 auto luaconfsCopy
= g_luaconfs
.getCopy();
8845 luaconfsCopy
.dsAnchors
.clear();
8846 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8847 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8848 g_luaconfs
.setState(luaconfsCopy
);
8850 size_t queriesCount
= 0;
8852 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
, bool* chained
) {
8855 DNSName auth
= domain
;
8858 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8859 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8862 setLWResult(res
, RCode::NoError
, true, false, true);
8863 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8864 addRRSIG(keys
, res
->d_records
, domain
, 300);
8865 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
8866 addRRSIG(keys
, res
->d_records
, domain
, 1);
8873 const time_t now
= sr
->getNow().tv_sec
;
8874 vector
<DNSRecord
> ret
;
8875 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8876 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8877 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8878 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8879 BOOST_CHECK_EQUAL(queriesCount
, 4);
8881 /* check that the entry has not been negatively cached for longer than the RRSIG validity */
8882 NegCache::NegCacheEntry ne
;
8883 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
8884 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
8885 BOOST_CHECK_EQUAL(ne
.d_ttd
, now
+ 1);
8886 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
8887 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
8888 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
8889 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
8890 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
8892 /* again, to test the cache */
8894 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8895 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8896 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8897 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8898 BOOST_CHECK_EQUAL(queriesCount
, 4);
8901 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_cache_validity
) {
8902 std::unique_ptr
<SyncRes
> sr
;
8905 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8908 const DNSName
target("com.");
8909 const ComboAddress
targetAddr("192.0.2.42");
8912 auto luaconfsCopy
= g_luaconfs
.getCopy();
8913 luaconfsCopy
.dsAnchors
.clear();
8914 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8915 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8916 g_luaconfs
.setState(luaconfsCopy
);
8918 size_t queriesCount
= 0;
8920 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
, bool* chained
) {
8923 DNSName auth
= domain
;
8926 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8927 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8930 setLWResult(res
, RCode::NoError
, true, false, true);
8931 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
8932 addRRSIG(keys
, res
->d_records
, domain
, 1);
8939 const time_t now
= sr
->getNow().tv_sec
;
8940 vector
<DNSRecord
> ret
;
8941 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8942 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8943 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8944 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8945 BOOST_CHECK_EQUAL(queriesCount
, 4);
8947 /* check that the entry has not been cached for longer than the RRSIG validity */
8948 const ComboAddress who
;
8949 vector
<DNSRecord
> cached
;
8950 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
8951 BOOST_REQUIRE_EQUAL(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
, &signatures
), 1);
8952 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
8953 BOOST_REQUIRE_EQUAL(signatures
.size(), 1);
8954 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), 1);
8956 /* again, to test the cache */
8958 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8959 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8960 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8961 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8962 BOOST_CHECK_EQUAL(queriesCount
, 4);
8965 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_secure
) {
8967 Validation is optional, and the first query does not ask for it,
8968 so the answer is cached as Indeterminate.
8969 The second query asks for validation, answer should be marked as
8972 std::unique_ptr
<SyncRes
> sr
;
8975 setDNSSECValidation(sr
, DNSSECMode::Process
);
8978 const DNSName
target("com.");
8981 auto luaconfsCopy
= g_luaconfs
.getCopy();
8982 luaconfsCopy
.dsAnchors
.clear();
8983 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8984 g_luaconfs
.setState(luaconfsCopy
);
8986 size_t queriesCount
= 0;
8988 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
, bool* chained
) {
8991 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8992 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8995 if (domain
== target
&& type
== QType::A
) {
8996 setLWResult(res
, 0, true, false, true);
8997 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8998 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9006 vector
<DNSRecord
> ret
;
9007 /* first query does not require validation */
9008 sr
->setDNSSECValidationRequested(false);
9009 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9010 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9011 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9012 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9013 for (const auto& record
: ret
) {
9014 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
9016 BOOST_CHECK_EQUAL(queriesCount
, 1);
9020 /* second one _does_ require validation */
9021 sr
->setDNSSECValidationRequested(true);
9022 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9023 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9024 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9025 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9026 for (const auto& record
: ret
) {
9027 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
9029 BOOST_CHECK_EQUAL(queriesCount
, 3);
9032 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_insecure
) {
9034 Validation is optional, and the first query does not ask for it,
9035 so the answer is cached as Indeterminate.
9036 The second query asks for validation, answer should be marked as
9039 std::unique_ptr
<SyncRes
> sr
;
9042 setDNSSECValidation(sr
, DNSSECMode::Process
);
9045 const DNSName
target("com.");
9048 auto luaconfsCopy
= g_luaconfs
.getCopy();
9049 luaconfsCopy
.dsAnchors
.clear();
9050 g_luaconfs
.setState(luaconfsCopy
);
9052 size_t queriesCount
= 0;
9054 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
, bool* chained
) {
9057 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9058 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9061 if (domain
== target
&& type
== QType::A
) {
9062 setLWResult(res
, 0, true, false, true);
9063 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
9071 vector
<DNSRecord
> ret
;
9072 /* first query does not require validation */
9073 sr
->setDNSSECValidationRequested(false);
9074 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9075 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9076 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9077 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9078 for (const auto& record
: ret
) {
9079 BOOST_CHECK(record
.d_type
== QType::A
);
9081 BOOST_CHECK_EQUAL(queriesCount
, 1);
9085 /* second one _does_ require validation */
9086 sr
->setDNSSECValidationRequested(true);
9087 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9088 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9089 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9090 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9091 for (const auto& record
: ret
) {
9092 BOOST_CHECK(record
.d_type
== QType::A
);
9094 BOOST_CHECK_EQUAL(queriesCount
, 1);
9097 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_bogus
) {
9099 Validation is optional, and the first query does not ask for it,
9100 so the answer is cached as Indeterminate.
9101 The second query asks for validation, answer should be marked as
9104 std::unique_ptr
<SyncRes
> sr
;
9107 setDNSSECValidation(sr
, DNSSECMode::Process
);
9110 const DNSName
target("com.");
9113 auto luaconfsCopy
= g_luaconfs
.getCopy();
9114 luaconfsCopy
.dsAnchors
.clear();
9115 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9116 g_luaconfs
.setState(luaconfsCopy
);
9118 size_t queriesCount
= 0;
9120 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
, bool* chained
) {
9123 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9124 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9127 if (domain
== target
&& type
== QType::A
) {
9128 setLWResult(res
, 0, true, false, true);
9129 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
9138 vector
<DNSRecord
> ret
;
9139 /* first query does not require validation */
9140 sr
->setDNSSECValidationRequested(false);
9141 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9142 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9143 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9144 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9145 for (const auto& record
: ret
) {
9146 BOOST_CHECK(record
.d_type
== QType::A
);
9148 BOOST_CHECK_EQUAL(queriesCount
, 1);
9152 /* second one _does_ require validation */
9153 sr
->setDNSSECValidationRequested(true);
9154 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9155 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9156 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9157 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9158 for (const auto& record
: ret
) {
9159 BOOST_CHECK(record
.d_type
== QType::A
);
9161 BOOST_CHECK_EQUAL(queriesCount
, 3);
9164 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_secure
) {
9166 Validation is optional, and the first query does not ask for it,
9167 so the answer is cached as Indeterminate.
9168 The second query asks for validation, answer should be marked as
9171 std::unique_ptr
<SyncRes
> sr
;
9174 setDNSSECValidation(sr
, DNSSECMode::Process
);
9177 const DNSName
target("com.");
9178 const DNSName
cnameTarget("cname-com.");
9181 auto luaconfsCopy
= g_luaconfs
.getCopy();
9182 luaconfsCopy
.dsAnchors
.clear();
9183 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9184 g_luaconfs
.setState(luaconfsCopy
);
9186 size_t queriesCount
= 0;
9188 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
, bool* chained
) {
9191 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9192 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9195 if (domain
== target
&& type
== QType::A
) {
9196 setLWResult(res
, 0, true, false, true);
9197 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
9198 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9199 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9200 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9202 } else if (domain
== cnameTarget
&& type
== QType::A
) {
9203 setLWResult(res
, 0, true, false, true);
9204 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9205 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9213 vector
<DNSRecord
> ret
;
9214 /* first query does not require validation */
9215 sr
->setDNSSECValidationRequested(false);
9216 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9217 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9218 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9219 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9220 for (const auto& record
: ret
) {
9221 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
9223 BOOST_CHECK_EQUAL(queriesCount
, 2);
9227 /* second one _does_ require validation */
9228 sr
->setDNSSECValidationRequested(true);
9229 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9230 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9231 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9232 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9233 for (const auto& record
: ret
) {
9234 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
9236 BOOST_CHECK_EQUAL(queriesCount
, 5);
9239 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_insecure
) {
9241 Validation is optional, and the first query does not ask for it,
9242 so the answer is cached as Indeterminate.
9243 The second query asks for validation, answer should be marked as
9246 std::unique_ptr
<SyncRes
> sr
;
9249 setDNSSECValidation(sr
, DNSSECMode::Process
);
9252 const DNSName
target("com.");
9253 const DNSName
cnameTarget("cname-com.");
9256 auto luaconfsCopy
= g_luaconfs
.getCopy();
9257 luaconfsCopy
.dsAnchors
.clear();
9258 g_luaconfs
.setState(luaconfsCopy
);
9260 size_t queriesCount
= 0;
9262 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
, bool* chained
) {
9265 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9266 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9269 if (domain
== target
&& type
== QType::A
) {
9270 setLWResult(res
, 0, true, false, true);
9271 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
9272 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9274 } else if (domain
== cnameTarget
&& type
== QType::A
) {
9275 setLWResult(res
, 0, true, false, true);
9276 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9284 vector
<DNSRecord
> ret
;
9285 /* first query does not require validation */
9286 sr
->setDNSSECValidationRequested(false);
9287 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9288 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9289 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9290 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9291 for (const auto& record
: ret
) {
9292 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9294 BOOST_CHECK_EQUAL(queriesCount
, 2);
9298 /* second one _does_ require validation */
9299 sr
->setDNSSECValidationRequested(true);
9300 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9301 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9302 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9303 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9304 for (const auto& record
: ret
) {
9305 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9307 BOOST_CHECK_EQUAL(queriesCount
, 2);
9310 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_bogus
) {
9312 Validation is optional, and the first query does not ask for it,
9313 so the answer is cached as Indeterminate.
9314 The second query asks for validation, answer should be marked as
9317 std::unique_ptr
<SyncRes
> sr
;
9320 setDNSSECValidation(sr
, DNSSECMode::Process
);
9323 const DNSName
target("com.");
9324 const DNSName
cnameTarget("cname-com.");
9327 auto luaconfsCopy
= g_luaconfs
.getCopy();
9328 luaconfsCopy
.dsAnchors
.clear();
9329 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9330 g_luaconfs
.setState(luaconfsCopy
);
9332 size_t queriesCount
= 0;
9334 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
, bool* chained
) {
9337 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9338 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9341 if (domain
== target
&& type
== QType::A
) {
9342 setLWResult(res
, 0, true, false, true);
9343 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
9344 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9347 } else if (domain
== cnameTarget
&& type
== QType::A
) {
9348 setLWResult(res
, 0, true, false, true);
9349 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9358 vector
<DNSRecord
> ret
;
9359 /* first query does not require validation */
9360 sr
->setDNSSECValidationRequested(false);
9361 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9362 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9363 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9364 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9365 for (const auto& record
: ret
) {
9366 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9368 BOOST_CHECK_EQUAL(queriesCount
, 2);
9372 /* second one _does_ require validation */
9373 sr
->setDNSSECValidationRequested(true);
9374 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9375 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9376 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9377 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9378 for (const auto& record
: ret
) {
9379 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9381 BOOST_CHECK_EQUAL(queriesCount
, 5);
9384 BOOST_AUTO_TEST_CASE(test_dnssec_validation_additional_without_rrsig
) {
9386 We get a record from a secure zone in the additional section, without
9387 the corresponding RRSIG. The record should not be marked as authoritative
9388 and should be correctly validated.
9390 std::unique_ptr
<SyncRes
> sr
;
9393 setDNSSECValidation(sr
, DNSSECMode::Process
);
9396 const DNSName
target("com.");
9397 const DNSName
addTarget("nsX.com.");
9400 auto luaconfsCopy
= g_luaconfs
.getCopy();
9401 luaconfsCopy
.dsAnchors
.clear();
9402 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9403 g_luaconfs
.setState(luaconfsCopy
);
9405 size_t queriesCount
= 0;
9407 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
, bool* chained
) {
9410 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9411 if (domain
== addTarget
) {
9412 DNSName
auth(domain
);
9413 /* no DS for com, auth will be . */
9415 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, false);
9417 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9420 if (domain
== target
&& type
== QType::A
) {
9421 setLWResult(res
, 0, true, false, true);
9422 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
9423 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9424 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42", DNSResourceRecord::ADDITIONAL
);
9425 /* no RRSIG for the additional record */
9427 } else if (domain
== addTarget
&& type
== QType::A
) {
9428 setLWResult(res
, 0, true, false, true);
9429 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42");
9430 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9438 vector
<DNSRecord
> ret
;
9439 /* first query for target/A, will pick up the additional record as non-auth / unvalidated */
9440 sr
->setDNSSECValidationRequested(false);
9441 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9442 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9443 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9444 BOOST_CHECK_EQUAL(ret
.size(), 2);
9445 for (const auto& record
: ret
) {
9446 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9448 BOOST_CHECK_EQUAL(queriesCount
, 1);
9451 /* ask for the additional record directly, we should not use
9452 the non-auth one and issue a new query, properly validated */
9453 sr
->setDNSSECValidationRequested(true);
9454 res
= sr
->beginResolve(addTarget
, QType(QType::A
), QClass::IN
, ret
);
9455 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9456 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9457 BOOST_CHECK_EQUAL(ret
.size(), 2);
9458 for (const auto& record
: ret
) {
9459 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9461 BOOST_CHECK_EQUAL(queriesCount
, 5);
9464 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure
) {
9466 Validation is optional, and the first query does not ask for it,
9467 so the answer is negatively cached as Indeterminate.
9468 The second query asks for validation, answer should be marked as
9471 std::unique_ptr
<SyncRes
> sr
;
9474 setDNSSECValidation(sr
, DNSSECMode::Process
);
9477 const DNSName
target("com.");
9480 auto luaconfsCopy
= g_luaconfs
.getCopy();
9481 luaconfsCopy
.dsAnchors
.clear();
9482 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9483 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9484 g_luaconfs
.setState(luaconfsCopy
);
9486 size_t queriesCount
= 0;
9488 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
, bool* chained
) {
9491 DNSName auth
= domain
;
9494 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9495 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9498 setLWResult(res
, RCode::NoError
, true, false, true);
9499 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9500 addRRSIG(keys
, res
->d_records
, domain
, 300);
9501 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
9502 addRRSIG(keys
, res
->d_records
, domain
, 1);
9509 vector
<DNSRecord
> ret
;
9510 /* first query does not require validation */
9511 sr
->setDNSSECValidationRequested(false);
9512 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9513 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9514 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9515 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9516 BOOST_CHECK_EQUAL(queriesCount
, 1);
9517 /* check that the entry has not been negatively cached */
9518 NegCache::NegCacheEntry ne
;
9519 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9520 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9521 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9522 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9523 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9524 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9525 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9528 /* second one _does_ require validation */
9529 sr
->setDNSSECValidationRequested(true);
9530 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9531 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9532 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9533 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9534 BOOST_CHECK_EQUAL(queriesCount
, 4);
9535 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9536 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9537 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
9538 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9539 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9540 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9541 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9544 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure_ds
) {
9546 Validation is optional, and the first query does not ask for it,
9547 so the answer is negatively cached as Indeterminate.
9548 The second query asks for validation, answer should be marked as
9550 The difference with test_dnssec_validation_from_negcache_secure is
9551 that have one more level here, so we are going to look for the proof
9552 that the DS does not exist for the last level. Since there is no cut,
9553 we should accept the fact that the NSEC denies DS and NS both.
9555 std::unique_ptr
<SyncRes
> sr
;
9558 setDNSSECValidation(sr
, DNSSECMode::Process
);
9561 const DNSName
target("www.com.");
9564 auto luaconfsCopy
= g_luaconfs
.getCopy();
9565 luaconfsCopy
.dsAnchors
.clear();
9566 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9567 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9568 g_luaconfs
.setState(luaconfsCopy
);
9570 size_t queriesCount
= 0;
9572 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
, bool* chained
) {
9575 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9576 if (domain
== target
) {
9577 /* there is no cut */
9578 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9580 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
9586 vector
<DNSRecord
> ret
;
9587 /* first query does not require validation */
9588 sr
->setDNSSECValidationRequested(false);
9589 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9590 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9591 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9592 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9593 BOOST_CHECK_EQUAL(queriesCount
, 1);
9596 /* second one _does_ require validation */
9597 sr
->setDNSSECValidationRequested(true);
9598 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9599 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9600 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9601 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9602 BOOST_CHECK_EQUAL(queriesCount
, 4);
9605 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_insecure
) {
9607 Validation is optional, and the first query does not ask for it,
9608 so the answer is negatively cached as Indeterminate.
9609 The second query asks for validation, answer should be marked as
9612 std::unique_ptr
<SyncRes
> sr
;
9615 setDNSSECValidation(sr
, DNSSECMode::Process
);
9618 const DNSName
target("com.");
9621 auto luaconfsCopy
= g_luaconfs
.getCopy();
9622 luaconfsCopy
.dsAnchors
.clear();
9623 g_luaconfs
.setState(luaconfsCopy
);
9625 size_t queriesCount
= 0;
9627 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
, bool* chained
) {
9630 DNSName auth
= domain
;
9633 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9634 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9637 setLWResult(res
, RCode::NoError
, true, false, true);
9638 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9645 vector
<DNSRecord
> ret
;
9646 /* first query does not require validation */
9647 sr
->setDNSSECValidationRequested(false);
9648 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9649 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9650 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9651 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9652 BOOST_CHECK_EQUAL(queriesCount
, 1);
9653 /* check that the entry has not been negatively cached */
9654 NegCache::NegCacheEntry ne
;
9655 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9656 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9657 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9658 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9659 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9660 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9661 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9664 /* second one _does_ require validation */
9665 sr
->setDNSSECValidationRequested(true);
9666 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9667 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9668 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9669 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9670 BOOST_CHECK_EQUAL(queriesCount
, 1);
9671 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9672 BOOST_CHECK_EQUAL(ne
.d_validationState
, Insecure
);
9673 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9674 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9675 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9676 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9679 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_bogus
) {
9681 Validation is optional, and the first query does not ask for it,
9682 so the answer is negatively cached as Indeterminate.
9683 The second query asks for validation, answer should be marked as
9686 std::unique_ptr
<SyncRes
> sr
;
9689 setDNSSECValidation(sr
, DNSSECMode::Process
);
9692 const DNSName
target("com.");
9695 auto luaconfsCopy
= g_luaconfs
.getCopy();
9696 luaconfsCopy
.dsAnchors
.clear();
9697 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9698 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9699 g_luaconfs
.setState(luaconfsCopy
);
9701 size_t queriesCount
= 0;
9703 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
, bool* chained
) {
9706 DNSName auth
= domain
;
9709 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9710 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9713 setLWResult(res
, RCode::NoError
, true, false, true);
9714 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9715 addRRSIG(keys
, res
->d_records
, domain
, 300);
9723 vector
<DNSRecord
> ret
;
9724 /* first query does not require validation */
9725 sr
->setDNSSECValidationRequested(false);
9726 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9727 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9728 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9729 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9730 BOOST_CHECK_EQUAL(queriesCount
, 1);
9731 NegCache::NegCacheEntry ne
;
9732 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9733 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9734 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9735 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9736 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9737 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9738 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9741 /* second one _does_ require validation */
9742 sr
->setDNSSECValidationRequested(true);
9743 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9744 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9745 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9746 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9747 BOOST_CHECK_EQUAL(queriesCount
, 4);
9748 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9749 BOOST_CHECK_EQUAL(ne
.d_validationState
, Bogus
);
9750 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9751 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9752 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9753 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9756 BOOST_AUTO_TEST_CASE(test_lowercase_outgoing
) {
9757 g_lowercaseOutgoing
= true;
9758 std::unique_ptr
<SyncRes
> sr
;
9763 vector
<DNSName
> sentOutQnames
;
9765 const DNSName
target("WWW.POWERDNS.COM");
9766 const DNSName
cname("WWW.PowerDNS.org");
9768 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
, bool* chained
) {
9770 sentOutQnames
.push_back(domain
);
9772 if (isRootServer(ip
)) {
9773 if (domain
== target
) {
9774 setLWResult(res
, 0, false, false, true);
9775 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
9776 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
9779 if (domain
== cname
) {
9780 setLWResult(res
, 0, false, false, true);
9781 addRecordToLW(res
, "powerdns.org.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
9782 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
9785 } else if (ip
== ComboAddress("192.0.2.1:53")) {
9786 if (domain
== target
) {
9787 setLWResult(res
, 0, true, false, false);
9788 addRecordToLW(res
, domain
, QType::CNAME
, cname
.toString());
9791 } else if (ip
== ComboAddress("192.0.2.2:53")) {
9792 if (domain
== cname
) {
9793 setLWResult(res
, 0, true, false, false);
9794 addRecordToLW(res
, domain
, QType::A
, "127.0.0.1");
9801 vector
<DNSRecord
> ret
;
9802 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9804 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9806 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9807 BOOST_CHECK_EQUAL(ret
[0].d_content
->getZoneRepresentation(), cname
.toString());
9809 BOOST_REQUIRE_EQUAL(sentOutQnames
.size(), 4);
9810 BOOST_CHECK_EQUAL(sentOutQnames
[0].toString(), target
.makeLowerCase().toString());
9811 BOOST_CHECK_EQUAL(sentOutQnames
[1].toString(), target
.makeLowerCase().toString());
9812 BOOST_CHECK_EQUAL(sentOutQnames
[2].toString(), cname
.makeLowerCase().toString());
9813 BOOST_CHECK_EQUAL(sentOutQnames
[3].toString(), cname
.makeLowerCase().toString());
9815 g_lowercaseOutgoing
= false;
9818 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo
) {
9819 std::unique_ptr
<SyncRes
> sr
;
9822 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9825 const DNSName
target("com.");
9826 testkeysset_t keys
, keys2
;
9828 auto luaconfsCopy
= g_luaconfs
.getCopy();
9829 luaconfsCopy
.dsAnchors
.clear();
9830 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9831 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9832 g_luaconfs
.setState(luaconfsCopy
);
9834 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9835 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9836 // But add the existing root key otherwise no RRSIG can be created
9837 auto rootkey
= keys
.find(g_rootdnsname
);
9838 keys2
.insert(*rootkey
);
9840 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
, bool* chained
) {
9841 DNSName auth
= domain
;
9843 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9844 if (domain
== target
) {
9845 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9849 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9855 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9856 BOOST_CHECK_EQUAL(state
, Secure
);
9857 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9858 for (const auto& i
: ds
) {
9859 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9863 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_all_sha
) {
9864 std::unique_ptr
<SyncRes
> sr
;
9867 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9870 const DNSName
target("com.");
9871 testkeysset_t keys
, keys2
, keys3
;
9873 auto luaconfsCopy
= g_luaconfs
.getCopy();
9874 luaconfsCopy
.dsAnchors
.clear();
9875 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9876 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9877 g_luaconfs
.setState(luaconfsCopy
);
9879 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9880 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9881 // But add the existing root key otherwise no RRSIG can be created
9882 auto rootkey
= keys
.find(g_rootdnsname
);
9883 keys2
.insert(*rootkey
);
9885 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys3
);
9886 // But add the existing root key otherwise no RRSIG can be created
9887 keys3
.insert(*rootkey
);
9889 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
, bool* chained
) {
9890 DNSName auth
= domain
;
9892 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9893 if (domain
== target
) {
9894 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9897 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9901 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9907 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9908 BOOST_CHECK_EQUAL(state
, Secure
);
9909 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9910 for (const auto& i
: ds
) {
9911 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
9915 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_two_highest
) {
9916 std::unique_ptr
<SyncRes
> sr
;
9919 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9922 const DNSName
target("com.");
9923 testkeysset_t keys
, keys2
, keys3
;
9925 auto luaconfsCopy
= g_luaconfs
.getCopy();
9926 luaconfsCopy
.dsAnchors
.clear();
9927 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9928 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9929 g_luaconfs
.setState(luaconfsCopy
);
9931 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9932 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys2
);
9933 // But add the existing root key otherwise no RRSIG can be created
9934 auto rootkey
= keys
.find(g_rootdnsname
);
9935 keys2
.insert(*rootkey
);
9937 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys3
);
9938 // But add the existing root key otherwise no RRSIG can be created
9939 keys3
.insert(*rootkey
);
9941 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
, bool* chained
) {
9942 DNSName auth
= domain
;
9944 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9945 if (domain
== target
) {
9946 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9949 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9953 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9959 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9960 BOOST_CHECK_EQUAL(state
, Secure
);
9961 BOOST_REQUIRE_EQUAL(ds
.size(), 2);
9962 for (const auto& i
: ds
) {
9963 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9968 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha384_over_gost
) {
9969 std::unique_ptr
<SyncRes
> sr
;
9972 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9975 const DNSName
target("com.");
9976 testkeysset_t keys
, keys2
;
9978 auto luaconfsCopy
= g_luaconfs
.getCopy();
9979 luaconfsCopy
.dsAnchors
.clear();
9980 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9981 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys
);
9982 g_luaconfs
.setState(luaconfsCopy
);
9984 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9985 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9986 // But add the existing root key otherwise no RRSIG can be created
9987 auto rootkey
= keys
.find(g_rootdnsname
);
9988 keys2
.insert(*rootkey
);
9990 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
, bool* chained
) {
9991 DNSName auth
= domain
;
9993 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9994 if (domain
== target
) {
9995 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9999 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
10005 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
10006 BOOST_CHECK_EQUAL(state
, Secure
);
10007 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
10008 for (const auto& i
: ds
) {
10009 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
10013 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha256_over_gost
) {
10014 std::unique_ptr
<SyncRes
> sr
;
10017 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
10020 const DNSName
target("com.");
10021 testkeysset_t keys
, keys2
;
10023 auto luaconfsCopy
= g_luaconfs
.getCopy();
10024 luaconfsCopy
.dsAnchors
.clear();
10025 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
10026 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
10027 g_luaconfs
.setState(luaconfsCopy
);
10029 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
10030 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
10031 // But add the existing root key otherwise no RRSIG can be created
10032 auto rootkey
= keys
.find(g_rootdnsname
);
10033 keys2
.insert(*rootkey
);
10035 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
, bool* chained
) {
10036 DNSName auth
= domain
;
10038 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
10039 if (domain
== target
) {
10040 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
10044 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
10050 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
10051 BOOST_CHECK_EQUAL(state
, Secure
);
10052 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
10053 for (const auto& i
: ds
) {
10054 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
10058 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_gost_over_sha1
) {
10059 std::unique_ptr
<SyncRes
> sr
;
10062 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
10065 const DNSName
target("com.");
10066 testkeysset_t keys
, keys2
;
10068 auto luaconfsCopy
= g_luaconfs
.getCopy();
10069 luaconfsCopy
.dsAnchors
.clear();
10070 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
10071 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys
);
10072 g_luaconfs
.setState(luaconfsCopy
);
10074 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
10075 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
10076 // But add the existing root key otherwise no RRSIG can be created
10077 auto rootkey
= keys
.find(g_rootdnsname
);
10078 keys2
.insert(*rootkey
);
10080 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
, bool* chained
) {
10081 DNSName auth
= domain
;
10083 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
10084 if (domain
== target
) {
10085 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
10089 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
10095 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
10096 BOOST_CHECK_EQUAL(state
, Secure
);
10097 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
10098 for (const auto& i
: ds
) {
10099 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::GOST
);
10102 #endif // HAVE_BOTAN110
10105 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
10107 - check out of band support
10109 - check preoutquery
10113 BOOST_AUTO_TEST_SUITE_END()