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_tc_fallback_to_tcp
) {
651 std::unique_ptr
<SyncRes
> sr
;
654 sr
->setAsyncCallback([](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
656 setLWResult(res
, 0, false, true, false);
659 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
660 setLWResult(res
, 0, true, false, false);
661 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
670 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
671 vector
<DNSRecord
> ret
;
672 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
673 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
676 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
) {
677 std::unique_ptr
<SyncRes
> sr
;
680 size_t tcpQueriesCount
= 0;
682 sr
->setAsyncCallback([&tcpQueriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
684 setLWResult(res
, 0, true, true, false);
688 /* first TCP query is answered with a TC response */
690 if (tcpQueriesCount
== 1) {
691 setLWResult(res
, 0, true, true, false);
694 setLWResult(res
, 0, true, false, false);
697 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
703 vector
<DNSRecord
> ret
;
704 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
705 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
706 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2);
709 BOOST_AUTO_TEST_CASE(test_all_nss_down
) {
710 std::unique_ptr
<SyncRes
> sr
;
712 std::set
<ComboAddress
> downServers
;
716 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
718 if (isRootServer(ip
)) {
719 setLWResult(res
, 0, false, false, true);
720 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
721 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
722 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
725 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
726 setLWResult(res
, 0, false, false, true);
727 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
728 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
729 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
730 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
731 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
732 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
736 downServers
.insert(ip
);
741 DNSName
target("powerdns.com.");
743 vector
<DNSRecord
> ret
;
744 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
745 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
746 BOOST_CHECK_EQUAL(ret
.size(), 0);
747 BOOST_CHECK_EQUAL(downServers
.size(), 4);
749 for (const auto& server
: downServers
) {
750 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
751 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
755 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
) {
756 std::unique_ptr
<SyncRes
> sr
;
758 std::set
<ComboAddress
> downServers
;
762 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
764 if (isRootServer(ip
)) {
765 setLWResult(res
, 0, false, false, true);
766 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
767 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
768 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
771 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
772 setLWResult(res
, 0, false, false, true);
773 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
774 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
775 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
776 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
777 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
778 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
782 downServers
.insert(ip
);
787 /* exact same test than the previous one, except instead of a time out we fake a network error */
788 DNSName
target("powerdns.com.");
790 vector
<DNSRecord
> ret
;
791 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
792 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
793 BOOST_CHECK_EQUAL(ret
.size(), 0);
794 BOOST_CHECK_EQUAL(downServers
.size(), 4);
796 for (const auto& server
: downServers
) {
797 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1);
798 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
802 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
) {
803 std::unique_ptr
<SyncRes
> sr
;
808 DNSName
target("www.powerdns.com.");
810 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
812 if (isRootServer(ip
)) {
813 setLWResult(res
, 0, false, false, true);
814 if (domain
== target
) {
815 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
816 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
817 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
818 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
820 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
821 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
822 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
823 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
824 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
828 else if (ip
== ComboAddress("192.0.2.3:53")) {
829 setLWResult(res
, 0, true, false, true);
830 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
831 if (type
== QType::A
) {
832 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
834 else if (type
== QType::AAAA
) {
835 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
838 else if (domain
== target
) {
839 if (type
== QType::A
) {
840 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
842 else if (type
== QType::AAAA
) {
843 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
851 vector
<DNSRecord
> ret
;
852 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
853 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
854 BOOST_CHECK_EQUAL(ret
.size(), 1);
857 BOOST_AUTO_TEST_CASE(test_os_limit_errors
) {
858 std::unique_ptr
<SyncRes
> sr
;
860 std::set
<ComboAddress
> downServers
;
864 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
866 if (isRootServer(ip
)) {
867 setLWResult(res
, 0, false, false, true);
868 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
869 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
870 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
873 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
874 setLWResult(res
, 0, false, false, true);
875 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
876 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
877 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
878 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
879 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
880 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
884 if (downServers
.size() < 3) {
885 /* only the last one will answer */
886 downServers
.insert(ip
);
890 setLWResult(res
, 0, true, false, true);
891 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
897 DNSName
target("powerdns.com.");
899 vector
<DNSRecord
> ret
;
900 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
901 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
902 BOOST_CHECK_EQUAL(ret
.size(), 1);
903 BOOST_CHECK_EQUAL(downServers
.size(), 3);
905 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
906 for (const auto& server
: downServers
) {
907 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0);
908 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
912 BOOST_AUTO_TEST_CASE(test_glued_referral
) {
913 std::unique_ptr
<SyncRes
> sr
;
918 const DNSName
target("powerdns.com.");
920 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
921 /* this will cause issue with qname minimization if we ever implement it */
922 if (domain
!= target
) {
926 if (isRootServer(ip
)) {
927 setLWResult(res
, 0, false, false, true);
928 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
929 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
930 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
933 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
934 setLWResult(res
, 0, false, false, true);
935 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
936 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
937 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
938 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
939 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
940 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
943 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
944 setLWResult(res
, 0, true, false, true);
945 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
953 vector
<DNSRecord
> ret
;
954 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
955 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
956 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
957 BOOST_CHECK(ret
[0].d_type
== QType::A
);
958 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
961 BOOST_AUTO_TEST_CASE(test_glueless_referral
) {
962 std::unique_ptr
<SyncRes
> sr
;
967 const DNSName
target("powerdns.com.");
969 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
971 if (isRootServer(ip
)) {
972 setLWResult(res
, 0, false, false, true);
974 if (domain
.isPartOf(DNSName("com."))) {
975 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
976 } else if (domain
.isPartOf(DNSName("org."))) {
977 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
980 setLWResult(res
, RCode::NXDomain
, false, false, true);
984 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
985 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
988 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
989 if (domain
== target
) {
990 setLWResult(res
, 0, false, false, true);
991 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
992 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
995 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
996 setLWResult(res
, 0, true, false, true);
997 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
998 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1001 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1002 setLWResult(res
, 0, true, false, true);
1003 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1004 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1008 setLWResult(res
, RCode::NXDomain
, false, false, true);
1011 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
1012 setLWResult(res
, 0, true, false, true);
1013 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1021 vector
<DNSRecord
> ret
;
1022 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1023 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1024 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1025 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1026 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1029 BOOST_AUTO_TEST_CASE(test_edns_submask_by_domain
) {
1030 std::unique_ptr
<SyncRes
> sr
;
1035 const DNSName
target("powerdns.com.");
1036 SyncRes::addEDNSDomain(target
);
1038 EDNSSubnetOpts incomingECS
;
1039 incomingECS
.source
= Netmask("192.0.2.128/32");
1040 sr
->setIncomingECSFound(true);
1041 sr
->setIncomingECS(incomingECS
);
1043 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1045 BOOST_REQUIRE(srcmask
);
1046 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1050 vector
<DNSRecord
> ret
;
1051 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1052 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1055 BOOST_AUTO_TEST_CASE(test_edns_submask_by_addr
) {
1056 std::unique_ptr
<SyncRes
> sr
;
1061 const DNSName
target("powerdns.com.");
1062 SyncRes::addEDNSSubnet(Netmask("192.0.2.1/32"));
1064 EDNSSubnetOpts incomingECS
;
1065 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1066 sr
->setIncomingECSFound(true);
1067 sr
->setIncomingECS(incomingECS
);
1069 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1071 if (isRootServer(ip
)) {
1072 BOOST_REQUIRE(!srcmask
);
1074 setLWResult(res
, 0, false, false, true);
1075 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1076 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1078 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1080 BOOST_REQUIRE(srcmask
);
1081 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1083 setLWResult(res
, 0, true, false, false);
1084 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1091 vector
<DNSRecord
> ret
;
1092 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1093 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1094 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1095 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1096 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1099 BOOST_AUTO_TEST_CASE(test_following_cname
) {
1100 std::unique_ptr
<SyncRes
> sr
;
1105 const DNSName
target("cname.powerdns.com.");
1106 const DNSName
cnameTarget("cname-target.powerdns.com");
1108 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1110 if (isRootServer(ip
)) {
1111 setLWResult(res
, 0, false, false, true);
1112 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1113 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1115 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1117 if (domain
== target
) {
1118 setLWResult(res
, 0, true, false, false);
1119 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1122 else if (domain
== cnameTarget
) {
1123 setLWResult(res
, 0, true, false, false);
1124 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1133 vector
<DNSRecord
> ret
;
1134 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1135 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1136 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1137 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1138 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1139 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1140 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1143 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
) {
1144 std::unique_ptr
<SyncRes
> sr
;
1149 const DNSName
target("cname.powerdns.com.");
1150 const DNSName
cnameTarget("cname-target.powerdns.com");
1152 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1154 if (isRootServer(ip
)) {
1155 setLWResult(res
, 0, false, false, true);
1156 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1157 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1159 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1161 if (domain
== target
) {
1162 setLWResult(res
, RCode::NXDomain
, true, false, false);
1163 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1164 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1165 } else if (domain
== cnameTarget
) {
1166 setLWResult(res
, RCode::NXDomain
, true, false, false);
1167 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1177 vector
<DNSRecord
> ret
;
1178 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1179 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1180 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1181 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1182 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1183 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1185 /* a second time, to check the cache */
1187 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1188 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1189 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1190 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1191 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1192 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1195 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
) {
1196 std::unique_ptr
<SyncRes
> sr
;
1201 /* In this test we directly get the NS server for cname.powerdns.com.,
1202 and we don't know whether it's also authoritative for
1203 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1204 the additional A record for cname-target.powerdns.com. */
1205 const DNSName
target("cname.powerdns.com.");
1206 const DNSName
cnameTarget("cname-target.powerdns.com");
1208 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1210 if (isRootServer(ip
)) {
1212 setLWResult(res
, 0, false, false, true);
1214 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1215 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1217 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1219 if (domain
== target
) {
1220 setLWResult(res
, 0, true, false, false);
1221 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1222 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1224 } else if (domain
== cnameTarget
) {
1225 setLWResult(res
, 0, true, false, false);
1226 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1236 vector
<DNSRecord
> ret
;
1237 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1238 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1239 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
1240 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1241 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1242 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1243 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1244 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1245 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1248 BOOST_AUTO_TEST_CASE(test_cname_loop
) {
1249 std::unique_ptr
<SyncRes
> sr
;
1255 const DNSName
target("cname.powerdns.com.");
1257 sr
->setAsyncCallback([target
,&count
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1261 if (isRootServer(ip
)) {
1263 setLWResult(res
, 0, false, false, true);
1264 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1265 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1267 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1269 if (domain
== target
) {
1270 setLWResult(res
, 0, true, false, false);
1271 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1281 vector
<DNSRecord
> ret
;
1282 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1283 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1284 BOOST_CHECK_GT(ret
.size(), 0);
1285 BOOST_CHECK_EQUAL(count
, 2);
1288 BOOST_AUTO_TEST_CASE(test_cname_depth
) {
1289 std::unique_ptr
<SyncRes
> sr
;
1295 const DNSName
target("cname.powerdns.com.");
1297 sr
->setAsyncCallback([target
,&depth
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1299 if (isRootServer(ip
)) {
1301 setLWResult(res
, 0, false, false, true);
1302 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1303 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1305 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1307 setLWResult(res
, 0, true, false, false);
1308 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(depth
) + "-cname.powerdns.com");
1316 vector
<DNSRecord
> ret
;
1317 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1318 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1319 BOOST_CHECK_EQUAL(ret
.size(), depth
);
1320 /* we have an arbitrary limit at 10 when following a CNAME chain */
1321 BOOST_CHECK_EQUAL(depth
, 10 + 2);
1324 BOOST_AUTO_TEST_CASE(test_time_limit
) {
1325 std::unique_ptr
<SyncRes
> sr
;
1331 const DNSName
target("cname.powerdns.com.");
1333 sr
->setAsyncCallback([target
,&queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1337 if (isRootServer(ip
)) {
1338 setLWResult(res
, 0, false, false, true);
1339 /* Pretend that this query took 2000 ms */
1342 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1343 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1345 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1347 setLWResult(res
, 0, true, false, false);
1348 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1355 /* Set the maximum time to 1 ms */
1356 SyncRes::s_maxtotusec
= 1000;
1359 vector
<DNSRecord
> ret
;
1360 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1363 catch(const ImmediateServFailException
& e
) {
1365 BOOST_CHECK_EQUAL(queries
, 1);
1368 BOOST_AUTO_TEST_CASE(test_referral_depth
) {
1369 std::unique_ptr
<SyncRes
> sr
;
1375 const DNSName
target("www.powerdns.com.");
1377 sr
->setAsyncCallback([target
,&queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1381 if (isRootServer(ip
)) {
1382 setLWResult(res
, 0, false, false, true);
1384 if (domain
== DNSName("www.powerdns.com.")) {
1385 addRecordToLW(res
, domain
, QType::NS
, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1387 else if (domain
== DNSName("ns.powerdns.com.")) {
1388 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1390 else if (domain
== DNSName("ns1.powerdns.org.")) {
1391 addRecordToLW(res
, domain
, QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1393 else if (domain
== DNSName("ns2.powerdns.org.")) {
1394 addRecordToLW(res
, domain
, QType::NS
, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1396 else if (domain
== DNSName("ns3.powerdns.org.")) {
1397 addRecordToLW(res
, domain
, QType::NS
, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1399 else if (domain
== DNSName("ns4.powerdns.org.")) {
1400 addRecordToLW(res
, domain
, QType::NS
, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1401 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::AUTHORITY
, 172800);
1405 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1407 setLWResult(res
, 0, true, false, false);
1408 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1415 /* Set the maximum depth low */
1416 SyncRes::s_maxdepth
= 10;
1419 vector
<DNSRecord
> ret
;
1420 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1423 catch(const ImmediateServFailException
& e
) {
1427 BOOST_AUTO_TEST_CASE(test_cname_qperq
) {
1428 std::unique_ptr
<SyncRes
> sr
;
1434 const DNSName
target("cname.powerdns.com.");
1436 sr
->setAsyncCallback([target
,&queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1440 if (isRootServer(ip
)) {
1442 setLWResult(res
, 0, false, false, true);
1443 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1444 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1446 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1448 setLWResult(res
, 0, true, false, false);
1449 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(queries
) + "-cname.powerdns.com");
1456 /* Set the maximum number of questions very low */
1457 SyncRes::s_maxqperq
= 5;
1460 vector
<DNSRecord
> ret
;
1461 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1464 catch(const ImmediateServFailException
& e
) {
1465 BOOST_CHECK_EQUAL(queries
, SyncRes::s_maxqperq
);
1469 BOOST_AUTO_TEST_CASE(test_throttled_server
) {
1470 std::unique_ptr
<SyncRes
> sr
;
1475 const DNSName
target("throttled.powerdns.com.");
1476 const ComboAddress
ns("192.0.2.1:53");
1477 size_t queriesToNS
= 0;
1479 sr
->setAsyncCallback([target
,ns
,&queriesToNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1481 if (isRootServer(ip
)) {
1483 setLWResult(res
, 0, false, false, true);
1484 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1485 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1487 } else if (ip
== ns
) {
1491 setLWResult(res
, 0, true, false, false);
1492 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1500 /* mark ns as down */
1501 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, 10000);
1503 vector
<DNSRecord
> ret
;
1504 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1505 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1506 BOOST_CHECK_EQUAL(ret
.size(), 0);
1507 /* we should not have sent any queries to ns */
1508 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1511 BOOST_AUTO_TEST_CASE(test_throttled_server_count
) {
1512 std::unique_ptr
<SyncRes
> sr
;
1517 const ComboAddress
ns("192.0.2.1:53");
1519 const size_t blocks
= 10;
1520 /* mark ns as down for 'blocks' queries */
1521 SyncRes::doThrottle(time(nullptr), ns
, SyncRes::s_serverdownthrottletime
, blocks
);
1523 for (size_t idx
= 0; idx
< blocks
; idx
++) {
1524 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1527 /* we have been throttled 'blocks' times, we should not be throttled anymore */
1528 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1531 BOOST_AUTO_TEST_CASE(test_throttled_server_time
) {
1532 std::unique_ptr
<SyncRes
> sr
;
1537 const ComboAddress
ns("192.0.2.1:53");
1539 const size_t seconds
= 1;
1540 /* mark ns as down for 'seconds' seconds */
1541 SyncRes::doThrottle(time(nullptr), ns
, seconds
, 10000);
1543 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns
));
1547 /* we should not be throttled anymore */
1548 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns
));
1551 BOOST_AUTO_TEST_CASE(test_dont_query_server
) {
1552 std::unique_ptr
<SyncRes
> sr
;
1557 const DNSName
target("throttled.powerdns.com.");
1558 const ComboAddress
ns("192.0.2.1:53");
1559 size_t queriesToNS
= 0;
1561 sr
->setAsyncCallback([target
,ns
,&queriesToNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1563 if (isRootServer(ip
)) {
1565 setLWResult(res
, 0, false, false, true);
1566 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1567 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1569 } else if (ip
== ns
) {
1573 setLWResult(res
, 0, true, false, false);
1574 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1582 /* prevent querying this NS */
1583 SyncRes::addDontQuery(Netmask(ns
));
1585 vector
<DNSRecord
> ret
;
1586 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1587 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1588 BOOST_CHECK_EQUAL(ret
.size(), 0);
1589 /* we should not have sent any queries to ns */
1590 BOOST_CHECK_EQUAL(queriesToNS
, 0);
1593 BOOST_AUTO_TEST_CASE(test_root_nx_trust
) {
1594 std::unique_ptr
<SyncRes
> sr
;
1599 const DNSName
target1("powerdns.com.");
1600 const DNSName
target2("notpowerdns.com.");
1601 const ComboAddress
ns("192.0.2.1:53");
1602 size_t queriesCount
= 0;
1604 sr
->setAsyncCallback([target1
, target2
, ns
, &queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1608 if (isRootServer(ip
)) {
1610 if (domain
== target1
) {
1611 setLWResult(res
, RCode::NXDomain
, true, false, true);
1612 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1615 setLWResult(res
, 0, true, false, true);
1616 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1617 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1621 } else if (ip
== ns
) {
1623 setLWResult(res
, 0, true, false, false);
1624 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1632 vector
<DNSRecord
> ret
;
1633 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1634 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1635 BOOST_CHECK_EQUAL(ret
.size(), 1);
1636 /* one for target1 and one for the entire TLD */
1637 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1640 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1641 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1642 BOOST_CHECK_EQUAL(ret
.size(), 1);
1643 /* one for target1 and one for the entire TLD */
1644 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
1646 /* we should have sent only one query */
1647 BOOST_CHECK_EQUAL(queriesCount
, 1);
1650 BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific
) {
1651 std::unique_ptr
<SyncRes
> sr
;
1653 initSR(sr
, true, false);
1657 const DNSName
target1("powerdns.com.");
1658 const DNSName
target2("notpowerdns.com.");
1659 const ComboAddress
ns("192.0.2.1:53");
1660 size_t queriesCount
= 0;
1662 /* This time the root denies target1 with a "com." SOA instead of a "." one.
1663 We should add target1 to the negcache, but not "com.". */
1665 sr
->setAsyncCallback([target1
, target2
, ns
, &queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1669 if (isRootServer(ip
)) {
1671 if (domain
== target1
) {
1672 setLWResult(res
, RCode::NXDomain
, true, false, true);
1673 addRecordToLW(res
, "com.", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1676 setLWResult(res
, 0, true, false, true);
1677 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1678 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1682 } else if (ip
== ns
) {
1684 setLWResult(res
, 0, true, false, false);
1685 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1693 vector
<DNSRecord
> ret
;
1694 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1695 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1696 BOOST_CHECK_EQUAL(ret
.size(), 1);
1698 /* even with root-nx-trust on and a NX answer from the root,
1699 we should not have cached the entire TLD this time. */
1700 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1703 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1704 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1705 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
1706 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1707 BOOST_CHECK_EQUAL(ret
[0].d_name
, target2
);
1708 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress("192.0.2.2"));
1710 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
1712 BOOST_CHECK_EQUAL(queriesCount
, 3);
1715 BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust
) {
1716 std::unique_ptr
<SyncRes
> sr
;
1721 const DNSName
target1("powerdns.com.");
1722 const DNSName
target2("notpowerdns.com.");
1723 const ComboAddress
ns("192.0.2.1:53");
1724 size_t queriesCount
= 0;
1726 sr
->setAsyncCallback([target1
, target2
, ns
, &queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1730 if (isRootServer(ip
)) {
1732 if (domain
== target1
) {
1733 setLWResult(res
, RCode::NXDomain
, true, false, true);
1734 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1737 setLWResult(res
, 0, true, false, true);
1738 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1739 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
1743 } else if (ip
== ns
) {
1745 setLWResult(res
, 0, true, false, false);
1746 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1754 SyncRes::s_rootNXTrust
= false;
1756 vector
<DNSRecord
> ret
;
1757 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1758 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1759 BOOST_CHECK_EQUAL(ret
.size(), 1);
1760 /* one for target1 */
1761 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1764 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
1765 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1766 BOOST_CHECK_EQUAL(ret
.size(), 1);
1767 /* one for target1 */
1768 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
1770 /* we should have sent three queries */
1771 BOOST_CHECK_EQUAL(queriesCount
, 3);
1774 BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response
) {
1775 std::unique_ptr
<SyncRes
> sr
;
1780 const DNSName
target("www.powerdns.com.");
1781 const DNSName
cnameTarget("cname.powerdns.com.");
1783 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
1785 EDNSSubnetOpts incomingECS
;
1786 incomingECS
.source
= Netmask("192.0.2.128/32");
1787 sr
->setIncomingECSFound(true);
1788 sr
->setIncomingECS(incomingECS
);
1790 sr
->setAsyncCallback([target
,cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1792 BOOST_REQUIRE(srcmask
);
1793 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1795 if (isRootServer(ip
)) {
1796 setLWResult(res
, 0, false, false, true);
1797 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1798 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1801 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1802 if (domain
== target
) {
1803 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
1804 setLWResult(res
, RCode::NXDomain
, true, false, true);
1805 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1806 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1808 else if (domain
== cnameTarget
) {
1809 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
1810 but we might if we still chase the CNAME. */
1811 setLWResult(res
, RCode::NXDomain
, true, false, true);
1812 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
1821 vector
<DNSRecord
> ret
;
1822 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1823 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1824 BOOST_CHECK_EQUAL(ret
.size(), 2);
1825 /* no negative cache entry because the response was variable */
1826 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0);
1829 BOOST_AUTO_TEST_CASE(test_ns_speed
) {
1830 std::unique_ptr
<SyncRes
> sr
;
1835 const DNSName
target("powerdns.com.");
1837 std::map
<ComboAddress
, uint64_t> nsCounts
;
1839 sr
->setAsyncCallback([target
,&nsCounts
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1841 if (isRootServer(ip
)) {
1842 setLWResult(res
, 0, false, false, true);
1843 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1844 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1845 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1847 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1848 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1849 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1850 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 3600);
1851 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 3600);
1852 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 3600);
1858 if (ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("192.0.2.2:53")) {
1859 BOOST_CHECK_LT(nsCounts
.size(), 3);
1861 /* let's time out on pdns-public-ns2.powerdns.com. */
1864 else if (ip
== ComboAddress("192.0.2.1:53")) {
1865 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1867 setLWResult(res
, 0, true, false, true);
1868 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1879 gettimeofday(&now
, 0);
1881 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1882 then pdns-public-ns1.powerdns.com. on IPv4 */
1883 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now
);
1884 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now
);
1885 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now
);
1886 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now
);
1887 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now
);
1888 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now
);
1890 vector
<DNSRecord
> ret
;
1891 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1892 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1893 BOOST_CHECK_EQUAL(ret
.size(), 1);
1894 BOOST_CHECK_EQUAL(nsCounts
.size(), 3);
1895 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.1:53")], 1);
1896 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.2:53")], 1);
1897 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("[2001:DB8::2]:53")], 1);
1900 BOOST_AUTO_TEST_CASE(test_flawed_nsset
) {
1901 std::unique_ptr
<SyncRes
> sr
;
1906 const DNSName
target("powerdns.com.");
1908 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1910 if (isRootServer(ip
)) {
1911 setLWResult(res
, 0, false, false, true);
1912 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1914 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1917 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1918 setLWResult(res
, 0, true, false, true);
1919 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1926 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1927 time_t now
= sr
->getNow().tv_sec
;
1928 std::vector
<DNSRecord
> records
;
1929 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1930 addRecordToList(records
, target
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, now
+ 3600);
1932 t_RC
->replace(now
, target
, QType(QType::NS
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1934 vector
<DNSRecord
> ret
;
1935 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1936 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1937 BOOST_CHECK_EQUAL(ret
.size(), 1);
1940 BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset
) {
1941 std::unique_ptr
<SyncRes
> sr
;
1946 const DNSName
target("powerdns.com.");
1947 size_t queriesCount
= 0;
1949 sr
->setAsyncCallback([&queriesCount
,target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1953 if (isRootServer(ip
) && domain
== target
) {
1954 setLWResult(res
, 0, false, false, true);
1955 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1956 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1958 } else if (domain
== DNSName("pdns-public-ns2.powerdns.com.") || domain
== DNSName("pdns-public-ns3.powerdns.com.")){
1959 setLWResult(res
, 0, true, false, true);
1960 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1967 vector
<DNSRecord
> ret
;
1968 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1969 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1970 BOOST_CHECK_EQUAL(ret
.size(), 0);
1971 /* one query to get NSs, then A and AAAA for each NS */
1972 BOOST_CHECK_EQUAL(queriesCount
, 5);
1975 BOOST_AUTO_TEST_CASE(test_cache_hit
) {
1976 std::unique_ptr
<SyncRes
> sr
;
1981 const DNSName
target("powerdns.com.");
1983 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
1988 /* we populate the cache with eveything we need */
1989 time_t now
= sr
->getNow().tv_sec
;
1990 std::vector
<DNSRecord
> records
;
1991 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1993 addRecordToList(records
, target
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, now
+ 3600);
1994 t_RC
->replace(now
, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1996 vector
<DNSRecord
> ret
;
1997 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1998 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1999 BOOST_CHECK_EQUAL(ret
.size(), 1);
2002 BOOST_AUTO_TEST_CASE(test_no_rd
) {
2003 std::unique_ptr
<SyncRes
> sr
;
2008 const DNSName
target("powerdns.com.");
2009 size_t queriesCount
= 0;
2013 sr
->setAsyncCallback([target
,&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2019 vector
<DNSRecord
> ret
;
2020 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2021 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2022 BOOST_CHECK_EQUAL(ret
.size(), 0);
2023 BOOST_CHECK_EQUAL(queriesCount
, 0);
2026 BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl
) {
2027 std::unique_ptr
<SyncRes
> sr
;
2032 const DNSName
target("cachettl.powerdns.com.");
2033 const ComboAddress
ns("192.0.2.1:53");
2035 sr
->setAsyncCallback([target
,ns
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2037 if (isRootServer(ip
)) {
2039 setLWResult(res
, 0, false, false, true);
2040 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2041 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 7200);
2043 } else if (ip
== ns
) {
2045 setLWResult(res
, 0, true, false, false);
2046 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
2054 const time_t now
= sr
->getNow().tv_sec
;
2055 SyncRes::s_minimumTTL
= 60;
2056 SyncRes::s_maxcachettl
= 3600;
2058 vector
<DNSRecord
> ret
;
2059 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2060 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2061 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2062 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumTTL
);
2064 const ComboAddress who
;
2065 vector
<DNSRecord
> cached
;
2066 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
2067 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2068 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2069 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
2072 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
2073 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
2074 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
2075 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
2078 BOOST_AUTO_TEST_CASE(test_cache_expired_ttl
) {
2079 std::unique_ptr
<SyncRes
> sr
;
2084 const DNSName
target("powerdns.com.");
2086 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2088 if (isRootServer(ip
)) {
2089 setLWResult(res
, 0, false, false, true);
2090 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2092 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2095 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2096 setLWResult(res
, 0, true, false, true);
2097 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2104 /* we populate the cache with entries that expired 60s ago*/
2105 time_t now
= sr
->getNow().tv_sec
;
2106 std::vector
<DNSRecord
> records
;
2107 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
2108 addRecordToList(records
, target
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, now
- 60);
2110 t_RC
->replace(now
- 3600, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
2112 vector
<DNSRecord
> ret
;
2113 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2114 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2115 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2116 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
2117 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
2120 BOOST_AUTO_TEST_CASE(test_delegation_only
) {
2121 std::unique_ptr
<SyncRes
> sr
;
2126 /* Thanks, Verisign */
2127 SyncRes::addDelegationOnly(DNSName("com."));
2128 SyncRes::addDelegationOnly(DNSName("net."));
2130 const DNSName
target("nx-powerdns.com.");
2132 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2134 if (isRootServer(ip
)) {
2135 setLWResult(res
, 0, false, false, true);
2136 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2137 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2139 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2141 setLWResult(res
, 0, true, false, true);
2142 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2149 vector
<DNSRecord
> ret
;
2150 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2151 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2152 BOOST_CHECK_EQUAL(ret
.size(), 0);
2155 BOOST_AUTO_TEST_CASE(test_unauth_any
) {
2156 std::unique_ptr
<SyncRes
> sr
;
2161 const DNSName
target("powerdns.com.");
2163 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2165 if (isRootServer(ip
)) {
2166 setLWResult(res
, 0, false, false, true);
2167 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2168 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2170 } else if (ip
== ComboAddress("192.0.2.1:53")) {
2172 setLWResult(res
, 0, false, false, true);
2173 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2180 vector
<DNSRecord
> ret
;
2181 int res
= sr
->beginResolve(target
, QType(QType::ANY
), QClass::IN
, ret
);
2182 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2183 BOOST_CHECK_EQUAL(ret
.size(), 0);
2186 BOOST_AUTO_TEST_CASE(test_no_data
) {
2187 std::unique_ptr
<SyncRes
> sr
;
2192 const DNSName
target("powerdns.com.");
2194 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2196 setLWResult(res
, 0, true, false, true);
2200 vector
<DNSRecord
> ret
;
2201 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2202 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2203 BOOST_CHECK_EQUAL(ret
.size(), 0);
2206 BOOST_AUTO_TEST_CASE(test_skip_opt_any
) {
2207 std::unique_ptr
<SyncRes
> sr
;
2212 const DNSName
target("powerdns.com.");
2214 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2216 setLWResult(res
, 0, true, false, true);
2217 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2218 addRecordToLW(res
, domain
, QType::ANY
, "0 0");
2219 addRecordToLW(res
, domain
, QType::OPT
, "");
2223 vector
<DNSRecord
> ret
;
2224 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2225 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2226 BOOST_CHECK_EQUAL(ret
.size(), 1);
2229 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec
) {
2230 std::unique_ptr
<SyncRes
> sr
;
2235 const DNSName
target("powerdns.com.");
2237 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2239 setLWResult(res
, 0, true, false, true);
2240 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2241 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2242 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2243 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2244 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2248 vector
<DNSRecord
> ret
;
2249 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2250 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2251 BOOST_CHECK_EQUAL(ret
.size(), 1);
2254 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec
) {
2255 std::unique_ptr
<SyncRes
> sr
;
2260 const DNSName
target("powerdns.com.");
2262 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2264 setLWResult(res
, 0, true, false, true);
2265 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2266 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2267 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2268 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2269 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2273 vector
<DNSRecord
> ret
;
2274 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2275 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2276 BOOST_CHECK_EQUAL(ret
.size(), 4);
2279 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec
) {
2280 std::unique_ptr
<SyncRes
> sr
;
2285 const DNSName
target("powerdns.com.");
2287 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2289 setLWResult(res
, RCode::NXDomain
, true, false, true);
2290 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2291 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2292 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2293 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2294 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2298 vector
<DNSRecord
> ret
;
2299 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2300 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2301 BOOST_CHECK_EQUAL(ret
.size(), 1);
2304 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec
) {
2305 std::unique_ptr
<SyncRes
> sr
;
2310 const DNSName
target("powerdns.com.");
2312 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2314 setLWResult(res
, RCode::NXDomain
, true, false, true);
2315 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
2316 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2317 addRecordToLW(res
, domain
, QType::NSEC
, "deadbeef", DNSResourceRecord::AUTHORITY
);
2318 addRecordToLW(res
, domain
, QType::RRSIG
, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2319 addRecordToLW(res
, domain
, QType::RRSIG
, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY
);
2323 vector
<DNSRecord
> ret
;
2324 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2325 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
2326 BOOST_CHECK_EQUAL(ret
.size(), 4);
2329 BOOST_AUTO_TEST_CASE(test_qclass_none
) {
2330 std::unique_ptr
<SyncRes
> sr
;
2335 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
2336 size_t queriesCount
= 0;
2338 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2344 const DNSName
target("powerdns.com.");
2345 vector
<DNSRecord
> ret
;
2346 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::NONE
, ret
);
2347 BOOST_CHECK_EQUAL(res
, -1);
2348 BOOST_CHECK_EQUAL(ret
.size(), 0);
2349 BOOST_CHECK_EQUAL(queriesCount
, 0);
2352 BOOST_AUTO_TEST_CASE(test_special_types
) {
2353 std::unique_ptr
<SyncRes
> sr
;
2358 /* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
2359 size_t queriesCount
= 0;
2361 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2363 cerr
<<"asyncresolve called to ask "<<ip
.toStringWithPort()<<" about "<<domain
.toString()<<" / "<<QType(type
).getName()<<" over "<<(doTCP
? "TCP" : "UDP")<<" (rd: "<<sendRDQuery
<<", EDNS0 level: "<<EDNS0Level
<<")"<<endl
;
2368 const DNSName
target("powerdns.com.");
2369 vector
<DNSRecord
> ret
;
2370 int res
= sr
->beginResolve(target
, QType(QType::AXFR
), QClass::IN
, ret
);
2371 BOOST_CHECK_EQUAL(res
, -1);
2372 BOOST_CHECK_EQUAL(ret
.size(), 0);
2373 BOOST_CHECK_EQUAL(queriesCount
, 0);
2375 res
= sr
->beginResolve(target
, QType(QType::IXFR
), QClass::IN
, ret
);
2376 BOOST_CHECK_EQUAL(res
, -1);
2377 BOOST_CHECK_EQUAL(ret
.size(), 0);
2378 BOOST_CHECK_EQUAL(queriesCount
, 0);
2380 res
= sr
->beginResolve(target
, QType(QType::RRSIG
), QClass::IN
, ret
);
2381 BOOST_CHECK_EQUAL(res
, -1);
2382 BOOST_CHECK_EQUAL(ret
.size(), 0);
2383 BOOST_CHECK_EQUAL(queriesCount
, 0);
2385 res
= sr
->beginResolve(target
, QType(QType::NSEC3
), QClass::IN
, ret
);
2386 BOOST_CHECK_EQUAL(res
, -1);
2387 BOOST_CHECK_EQUAL(ret
.size(), 0);
2388 BOOST_CHECK_EQUAL(queriesCount
, 0);
2391 BOOST_AUTO_TEST_CASE(test_special_names
) {
2392 std::unique_ptr
<SyncRes
> sr
;
2397 /* special names should be handled internally */
2399 size_t queriesCount
= 0;
2401 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2407 vector
<DNSRecord
> ret
;
2408 int res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
2409 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2410 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2411 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2412 BOOST_CHECK_EQUAL(queriesCount
, 0);
2415 res
= sr
->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
2416 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2417 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2418 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2419 BOOST_CHECK_EQUAL(queriesCount
, 0);
2422 res
= sr
->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::PTR
), QClass::IN
, ret
);
2423 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2424 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2425 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2426 BOOST_CHECK_EQUAL(queriesCount
, 0);
2429 res
= sr
->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::ANY
), QClass::IN
, ret
);
2430 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2431 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2432 BOOST_CHECK(ret
[0].d_type
== QType::PTR
);
2433 BOOST_CHECK_EQUAL(queriesCount
, 0);
2436 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::A
), QClass::IN
, ret
);
2437 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2438 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2439 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2440 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), "127.0.0.1");
2441 BOOST_CHECK_EQUAL(queriesCount
, 0);
2444 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::AAAA
), QClass::IN
, ret
);
2445 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2446 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2447 BOOST_CHECK(ret
[0].d_type
== QType::AAAA
);
2448 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(ret
[0])->getCA().toString(), "::1");
2449 BOOST_CHECK_EQUAL(queriesCount
, 0);
2452 res
= sr
->beginResolve(DNSName("localhost."), QType(QType::ANY
), QClass::IN
, ret
);
2453 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2454 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2455 for (const auto& rec
: ret
) {
2456 BOOST_REQUIRE((rec
.d_type
== QType::A
) || rec
.d_type
== QType::AAAA
);
2457 if (rec
.d_type
== QType::A
) {
2458 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(rec
)->getCA().toString(), "127.0.0.1");
2461 BOOST_CHECK_EQUAL(getRR
<AAAARecordContent
>(rec
)->getCA().toString(), "::1");
2464 BOOST_CHECK_EQUAL(queriesCount
, 0);
2467 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2468 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2469 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2470 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2471 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2472 BOOST_CHECK_EQUAL(queriesCount
, 0);
2475 res
= sr
->beginResolve(DNSName("version.bind."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2476 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2477 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2478 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2479 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2480 BOOST_CHECK_EQUAL(queriesCount
, 0);
2483 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2484 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2485 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2486 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2487 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2488 BOOST_CHECK_EQUAL(queriesCount
, 0);
2491 res
= sr
->beginResolve(DNSName("version.pdns."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2492 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2493 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2494 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2495 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests\"");
2496 BOOST_CHECK_EQUAL(queriesCount
, 0);
2499 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::TXT
), QClass::CHAOS
, ret
);
2500 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2501 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2502 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2503 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2504 BOOST_CHECK_EQUAL(queriesCount
, 0);
2507 res
= sr
->beginResolve(DNSName("id.server."), QType(QType::ANY
), QClass::CHAOS
, ret
);
2508 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2509 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2510 BOOST_CHECK(ret
[0].d_type
== QType::TXT
);
2511 BOOST_CHECK_EQUAL(getRR
<TXTRecordContent
>(ret
[0])->d_text
, "\"PowerDNS Unit Tests Server ID\"");
2512 BOOST_CHECK_EQUAL(queriesCount
, 0);
2515 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz
) {
2516 std::unique_ptr
<SyncRes
> sr
;
2521 const DNSName
target("rpz.powerdns.com.");
2522 const ComboAddress
ns("192.0.2.1:53");
2524 sr
->setAsyncCallback([target
,ns
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2526 if (isRootServer(ip
)) {
2527 setLWResult(res
, false, true, false, true);
2528 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2529 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2531 } else if (ip
== ns
) {
2533 setLWResult(res
, 0, true, false, true);
2534 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2541 DNSFilterEngine::Policy pol
;
2542 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2543 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2544 zone
->setName("Unit test policy 0");
2545 zone
->addNSIPTrigger(Netmask(ns
, 32), pol
);
2546 auto luaconfsCopy
= g_luaconfs
.getCopy();
2547 luaconfsCopy
.dfe
.addZone(zone
);
2548 g_luaconfs
.setState(luaconfsCopy
);
2550 vector
<DNSRecord
> ret
;
2551 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2552 BOOST_CHECK_EQUAL(res
, -2);
2553 BOOST_CHECK_EQUAL(ret
.size(), 0);
2556 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz
) {
2557 std::unique_ptr
<SyncRes
> sr
;
2562 const DNSName
target("rpz.powerdns.com.");
2563 const ComboAddress
ns("[2001:DB8::42]:53");
2565 sr
->setAsyncCallback([target
,ns
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2567 if (isRootServer(ip
)) {
2568 setLWResult(res
, 0, false, false, true);
2569 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2570 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2572 } else if (ip
== ns
) {
2574 setLWResult(res
, 0, true, false, true);
2575 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2582 DNSFilterEngine::Policy pol
;
2583 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2584 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2585 zone
->setName("Unit test policy 0");
2586 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2587 auto luaconfsCopy
= g_luaconfs
.getCopy();
2588 luaconfsCopy
.dfe
.addZone(zone
);
2589 g_luaconfs
.setState(luaconfsCopy
);
2591 vector
<DNSRecord
> ret
;
2592 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2593 BOOST_CHECK_EQUAL(res
, -2);
2594 BOOST_CHECK_EQUAL(ret
.size(), 0);
2597 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz
) {
2598 std::unique_ptr
<SyncRes
> sr
;
2603 const DNSName
target("rpz.powerdns.com.");
2604 const ComboAddress
ns("192.0.2.1:53");
2605 const DNSName
nsName("ns1.powerdns.com.");
2607 sr
->setAsyncCallback([target
,ns
,nsName
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2609 if (isRootServer(ip
)) {
2610 setLWResult(res
, 0, false, false, true);
2611 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2612 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2614 } else if (ip
== ns
) {
2616 setLWResult(res
, 0, true, false, true);
2617 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2624 DNSFilterEngine::Policy pol
;
2625 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2626 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2627 zone
->setName("Unit test policy 0");
2628 zone
->addNSTrigger(nsName
, pol
);
2629 auto luaconfsCopy
= g_luaconfs
.getCopy();
2630 luaconfsCopy
.dfe
.addZone(zone
);
2631 g_luaconfs
.setState(luaconfsCopy
);
2633 vector
<DNSRecord
> ret
;
2634 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2635 BOOST_CHECK_EQUAL(res
, -2);
2636 BOOST_CHECK_EQUAL(ret
.size(), 0);
2639 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled
) {
2640 std::unique_ptr
<SyncRes
> sr
;
2645 const DNSName
target("rpz.powerdns.com.");
2646 const ComboAddress
ns("192.0.2.1:53");
2647 const DNSName
nsName("ns1.powerdns.com.");
2649 sr
->setAsyncCallback([target
,ns
,nsName
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2651 if (isRootServer(ip
)) {
2652 setLWResult(res
, 0, false, false, true);
2653 addRecordToLW(res
, domain
, QType::NS
, nsName
.toString(), DNSResourceRecord::AUTHORITY
, 172800);
2654 addRecordToLW(res
, nsName
, QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
2656 } else if (ip
== ns
) {
2658 setLWResult(res
, 0, true, false, true);
2659 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2666 DNSFilterEngine::Policy pol
;
2667 pol
.d_kind
= DNSFilterEngine::PolicyKind::Drop
;
2668 std::shared_ptr
<DNSFilterEngine::Zone
> zone
= std::make_shared
<DNSFilterEngine::Zone
>();
2669 zone
->setName("Unit test policy 0");
2670 zone
->addNSIPTrigger(Netmask(ns
, 128), pol
);
2671 zone
->addNSTrigger(nsName
, pol
);
2672 auto luaconfsCopy
= g_luaconfs
.getCopy();
2673 luaconfsCopy
.dfe
.addZone(zone
);
2674 g_luaconfs
.setState(luaconfsCopy
);
2676 /* RPZ is disabled for this query, we should not be blocked */
2677 sr
->setWantsRPZ(false);
2679 vector
<DNSRecord
> ret
;
2680 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2681 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2682 BOOST_CHECK_EQUAL(ret
.size(), 1);
2685 BOOST_AUTO_TEST_CASE(test_forward_zone_nord
) {
2686 std::unique_ptr
<SyncRes
> sr
;
2691 const DNSName
target("powerdns.com.");
2692 const ComboAddress
ns("192.0.2.1:53");
2693 const ComboAddress
forwardedNS("192.0.2.42:53");
2695 SyncRes::AuthDomain ad
;
2696 ad
.d_rdForward
= false;
2697 ad
.d_servers
.push_back(forwardedNS
);
2698 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2700 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2702 if (ip
== forwardedNS
) {
2703 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2705 setLWResult(res
, 0, true, false, true);
2706 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2713 /* simulate a no-RD query */
2716 vector
<DNSRecord
> ret
;
2717 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2718 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2719 BOOST_CHECK_EQUAL(ret
.size(), 1);
2722 BOOST_AUTO_TEST_CASE(test_forward_zone_rd
) {
2723 std::unique_ptr
<SyncRes
> sr
;
2728 const DNSName
target("powerdns.com.");
2729 const ComboAddress
ns("192.0.2.1:53");
2730 const ComboAddress
forwardedNS("192.0.2.42:53");
2732 SyncRes::AuthDomain ad
;
2733 ad
.d_rdForward
= false;
2734 ad
.d_servers
.push_back(forwardedNS
);
2735 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2737 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2739 if (ip
== forwardedNS
) {
2740 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2742 setLWResult(res
, 0, true, false, true);
2743 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2750 vector
<DNSRecord
> ret
;
2751 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2752 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2753 BOOST_CHECK_EQUAL(ret
.size(), 1);
2756 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord
) {
2757 std::unique_ptr
<SyncRes
> sr
;
2762 const DNSName
target("powerdns.com.");
2763 const ComboAddress
ns("192.0.2.1:53");
2764 const ComboAddress
forwardedNS("192.0.2.42:53");
2766 SyncRes::AuthDomain ad
;
2767 ad
.d_rdForward
= true;
2768 ad
.d_servers
.push_back(forwardedNS
);
2769 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2771 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2773 if (ip
== forwardedNS
) {
2774 BOOST_CHECK_EQUAL(sendRDQuery
, false);
2776 setLWResult(res
, 0, true, false, true);
2777 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2784 /* simulate a no-RD query */
2787 vector
<DNSRecord
> ret
;
2788 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2789 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2790 BOOST_CHECK_EQUAL(ret
.size(), 1);
2793 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd
) {
2794 std::unique_ptr
<SyncRes
> sr
;
2799 const DNSName
target("powerdns.com.");
2800 const ComboAddress
ns("192.0.2.1:53");
2801 const ComboAddress
forwardedNS("192.0.2.42:53");
2803 SyncRes::AuthDomain ad
;
2804 ad
.d_rdForward
= true;
2805 ad
.d_servers
.push_back(forwardedNS
);
2806 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
2808 sr
->setAsyncCallback([forwardedNS
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2810 if (ip
== forwardedNS
) {
2811 BOOST_CHECK_EQUAL(sendRDQuery
, true);
2813 setLWResult(res
, 0, true, false, true);
2814 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2821 vector
<DNSRecord
> ret
;
2822 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2823 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2824 BOOST_CHECK_EQUAL(ret
.size(), 1);
2827 BOOST_AUTO_TEST_CASE(test_auth_zone_oob
) {
2828 std::unique_ptr
<SyncRes
> sr
;
2833 size_t queriesCount
= 0;
2834 const DNSName
target("test.xx.");
2835 const ComboAddress
targetAddr("127.0.0.1");
2836 const DNSName
authZone("test.xx");
2838 SyncRes::AuthDomain ad
;
2841 dr
.d_place
= DNSResourceRecord::ANSWER
;
2843 dr
.d_type
= QType::A
;
2845 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
2846 ad
.d_records
.insert(dr
);
2848 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
2850 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2855 vector
<DNSRecord
> ret
;
2856 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2857 BOOST_CHECK_EQUAL(res
, 0);
2858 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2859 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2860 BOOST_CHECK_EQUAL(queriesCount
, 0);
2861 BOOST_CHECK(sr
->wasOutOfBand());
2862 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2864 /* a second time, to check that the OOB flag is set when the query cache is used */
2866 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2867 BOOST_CHECK_EQUAL(res
, 0);
2868 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2869 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2870 BOOST_CHECK_EQUAL(queriesCount
, 0);
2871 BOOST_CHECK(sr
->wasOutOfBand());
2872 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2874 /* a third time, to check that the validation is disabled when the OOB flag is set */
2876 sr
->setDNSSECValidationRequested(true);
2877 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2878 BOOST_CHECK_EQUAL(res
, 0);
2879 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
2880 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2881 BOOST_CHECK_EQUAL(queriesCount
, 0);
2882 BOOST_CHECK(sr
->wasOutOfBand());
2883 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2886 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_cname
) {
2887 std::unique_ptr
<SyncRes
> sr
;
2892 size_t queriesCount
= 0;
2893 const DNSName
target("cname.test.xx.");
2894 const DNSName
targetCname("cname-target.test.xx.");
2895 const ComboAddress
targetCnameAddr("127.0.0.1");
2896 const DNSName
authZone("test.xx");
2898 SyncRes::AuthDomain ad
;
2901 dr
.d_place
= DNSResourceRecord::ANSWER
;
2903 dr
.d_type
= QType::CNAME
;
2905 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(targetCname
);
2906 ad
.d_records
.insert(dr
);
2908 dr
.d_place
= DNSResourceRecord::ANSWER
;
2909 dr
.d_name
= targetCname
;
2910 dr
.d_type
= QType::A
;
2912 dr
.d_content
= std::make_shared
<ARecordContent
>(targetCnameAddr
);
2913 ad
.d_records
.insert(dr
);
2915 (*SyncRes::t_sstorage
.domainmap
)[authZone
] = ad
;
2917 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2922 vector
<DNSRecord
> ret
;
2923 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2924 BOOST_CHECK_EQUAL(res
, 0);
2925 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2926 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2927 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2928 BOOST_CHECK_EQUAL(queriesCount
, 0);
2929 BOOST_CHECK(sr
->wasOutOfBand());
2930 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2932 /* a second time, to check that the OOB flag is set when the query cache is used */
2934 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2935 BOOST_CHECK_EQUAL(res
, 0);
2936 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2937 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2938 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2939 BOOST_CHECK_EQUAL(queriesCount
, 0);
2940 BOOST_CHECK(sr
->wasOutOfBand());
2941 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2943 /* a third time, to check that the validation is disabled when the OOB flag is set */
2945 sr
->setDNSSECValidationRequested(true);
2946 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2947 BOOST_CHECK_EQUAL(res
, 0);
2948 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
2949 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
2950 BOOST_CHECK(ret
[1].d_type
== QType::A
);
2951 BOOST_CHECK_EQUAL(queriesCount
, 0);
2952 BOOST_CHECK(sr
->wasOutOfBand());
2953 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
2956 BOOST_AUTO_TEST_CASE(test_auth_zone
) {
2957 std::unique_ptr
<SyncRes
> sr
;
2962 size_t queriesCount
= 0;
2963 const DNSName
target("powerdns.com.");
2964 const ComboAddress
addr("192.0.2.5");
2966 SyncRes::AuthDomain ad
;
2969 dr
.d_place
= DNSResourceRecord::ANSWER
;
2971 dr
.d_type
= QType::SOA
;
2973 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2974 ad
.d_records
.insert(dr
);
2976 dr
.d_place
= DNSResourceRecord::ANSWER
;
2978 dr
.d_type
= QType::A
;
2980 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
2981 ad
.d_records
.insert(dr
);
2983 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
2984 (*map
)[target
] = ad
;
2985 SyncRes::setDomainMap(map
);
2987 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
2990 setLWResult(res
, 0, true, false, true);
2991 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2995 vector
<DNSRecord
> ret
;
2996 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2997 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2998 BOOST_CHECK_EQUAL(ret
.size(), 1);
2999 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3000 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3001 BOOST_CHECK_EQUAL(queriesCount
, 0);
3004 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob
) {
3005 std::unique_ptr
<SyncRes
> sr
;
3010 size_t queriesCount
= 0;
3011 const DNSName
target("powerdns.com.");
3012 const DNSName
authZone("internal.powerdns.com.");
3013 const ComboAddress
addr("192.0.2.5");
3015 SyncRes::AuthDomain ad
;
3016 ad
.d_name
= authZone
;
3018 dr
.d_place
= DNSResourceRecord::ANSWER
;
3019 dr
.d_name
= authZone
;
3020 dr
.d_type
= QType::SOA
;
3022 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3023 ad
.d_records
.insert(dr
);
3025 dr
.d_place
= DNSResourceRecord::ANSWER
;
3026 dr
.d_name
= authZone
;
3027 dr
.d_type
= QType::A
;
3029 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3030 ad
.d_records
.insert(dr
);
3032 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3033 (*map
)[authZone
] = ad
;
3034 SyncRes::setDomainMap(map
);
3036 sr
->setAsyncCallback([&queriesCount
,target
,authZone
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3040 if (domain
== target
) {
3041 setLWResult(res
, 0, true, false, true);
3042 addRecordToLW(res
, target
, QType::CNAME
, authZone
.toString(), DNSResourceRecord::ANSWER
, 3600);
3049 vector
<DNSRecord
> ret
;
3050 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3051 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3052 BOOST_CHECK_EQUAL(ret
.size(), 2);
3053 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3054 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), authZone
.toString());
3055 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3056 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
3057 BOOST_CHECK_EQUAL(queriesCount
, 1);
3060 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb
) {
3061 std::unique_ptr
<SyncRes
> sr
;
3066 size_t queriesCount
= 0;
3067 const DNSName
target("powerdns.com.");
3068 const DNSName
externalCNAME("www.open-xchange.com.");
3069 const ComboAddress
addr("192.0.2.5");
3071 SyncRes::AuthDomain ad
;
3074 dr
.d_place
= DNSResourceRecord::ANSWER
;
3076 dr
.d_type
= QType::SOA
;
3078 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3079 ad
.d_records
.insert(dr
);
3081 dr
.d_place
= DNSResourceRecord::ANSWER
;
3083 dr
.d_type
= QType::CNAME
;
3085 dr
.d_content
= std::make_shared
<CNAMERecordContent
>(externalCNAME
);
3086 ad
.d_records
.insert(dr
);
3088 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3089 (*map
)[target
] = ad
;
3090 SyncRes::setDomainMap(map
);
3092 sr
->setAsyncCallback([&queriesCount
,externalCNAME
,addr
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3096 if (domain
== externalCNAME
) {
3097 setLWResult(res
, 0, true, false, true);
3098 addRecordToLW(res
, externalCNAME
, QType::A
, addr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3105 vector
<DNSRecord
> ret
;
3106 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3107 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3108 BOOST_CHECK_EQUAL(ret
.size(), 2);
3109 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
3110 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget().toString(), externalCNAME
.toString());
3111 BOOST_CHECK(ret
[1].d_type
== QType::A
);
3112 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[1])->getCA().toString(), addr
.toString());
3113 BOOST_CHECK_EQUAL(queriesCount
, 1);
3116 BOOST_AUTO_TEST_CASE(test_auth_zone_nodata
) {
3117 std::unique_ptr
<SyncRes
> sr
;
3122 size_t queriesCount
= 0;
3123 const DNSName
target("nodata.powerdns.com.");
3124 const DNSName
authZone("powerdns.com");
3126 SyncRes::AuthDomain ad
;
3127 ad
.d_name
= authZone
;
3129 dr
.d_place
= DNSResourceRecord::ANSWER
;
3131 dr
.d_type
= QType::A
;
3133 dr
.d_content
= std::make_shared
<ARecordContent
>(ComboAddress("192.0.2.1"));
3134 ad
.d_records
.insert(dr
);
3136 dr
.d_place
= DNSResourceRecord::ANSWER
;
3137 dr
.d_name
= authZone
;
3138 dr
.d_type
= QType::SOA
;
3140 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3141 ad
.d_records
.insert(dr
);
3143 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3144 (*map
)[authZone
] = ad
;
3145 SyncRes::setDomainMap(map
);
3147 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3154 vector
<DNSRecord
> ret
;
3155 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3156 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3157 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3158 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3159 BOOST_CHECK_EQUAL(queriesCount
, 0);
3162 BOOST_AUTO_TEST_CASE(test_auth_zone_nx
) {
3163 std::unique_ptr
<SyncRes
> sr
;
3168 size_t queriesCount
= 0;
3169 const DNSName
target("nx.powerdns.com.");
3170 const DNSName
authZone("powerdns.com");
3172 SyncRes::AuthDomain ad
;
3173 ad
.d_name
= authZone
;
3175 dr
.d_place
= DNSResourceRecord::ANSWER
;
3176 dr
.d_name
= DNSName("powerdns.com.");
3177 dr
.d_type
= QType::SOA
;
3179 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3180 ad
.d_records
.insert(dr
);
3182 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3183 (*map
)[authZone
] = ad
;
3184 SyncRes::setDomainMap(map
);
3186 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3193 vector
<DNSRecord
> ret
;
3194 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3195 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
3196 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3197 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3198 BOOST_CHECK_EQUAL(queriesCount
, 0);
3201 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation
) {
3202 std::unique_ptr
<SyncRes
> sr
;
3203 initSR(sr
, true, false);
3207 size_t queriesCount
= 0;
3208 const DNSName
target("www.test.powerdns.com.");
3209 const ComboAddress
targetAddr("192.0.2.2");
3210 const DNSName
ns("ns1.test.powerdns.com.");
3211 const ComboAddress
nsAddr("192.0.2.1");
3212 const DNSName
authZone("powerdns.com");
3214 SyncRes::AuthDomain ad
;
3215 ad
.d_name
= authZone
;
3217 dr
.d_place
= DNSResourceRecord::ANSWER
;
3218 dr
.d_name
= authZone
;
3219 dr
.d_type
= QType::SOA
;
3221 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3222 ad
.d_records
.insert(dr
);
3224 dr
.d_place
= DNSResourceRecord::ANSWER
;
3225 dr
.d_name
= DNSName("test.powerdns.com.");
3226 dr
.d_type
= QType::NS
;
3228 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3229 ad
.d_records
.insert(dr
);
3231 dr
.d_place
= DNSResourceRecord::ANSWER
;
3233 dr
.d_type
= QType::A
;
3235 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3236 ad
.d_records
.insert(dr
);
3238 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3239 (*map
)[authZone
] = ad
;
3240 SyncRes::setDomainMap(map
);
3243 auto luaconfsCopy
= g_luaconfs
.getCopy();
3244 luaconfsCopy
.dsAnchors
.clear();
3245 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
3246 g_luaconfs
.setState(luaconfsCopy
);
3248 sr
->setAsyncCallback([&queriesCount
,target
,targetAddr
,nsAddr
,authZone
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3251 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
3252 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
, domain
== authZone
);
3255 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3256 setLWResult(res
, 0, true, false, true);
3257 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3264 sr
->setDNSSECValidationRequested(true);
3265 vector
<DNSRecord
> ret
;
3266 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3267 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3268 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3269 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3270 BOOST_CHECK_EQUAL(queriesCount
, 4);
3271 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
3274 BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point
) {
3275 std::unique_ptr
<SyncRes
> sr
;
3280 size_t queriesCount
= 0;
3281 const DNSName
target("test.powerdns.com.");
3282 const ComboAddress
targetAddr("192.0.2.2");
3283 const DNSName
ns("ns1.test.powerdns.com.");
3284 const ComboAddress
nsAddr("192.0.2.1");
3285 const DNSName
authZone("powerdns.com");
3287 SyncRes::AuthDomain ad
;
3288 ad
.d_name
= authZone
;
3290 dr
.d_place
= DNSResourceRecord::ANSWER
;
3291 dr
.d_name
= authZone
;
3292 dr
.d_type
= QType::SOA
;
3294 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3295 ad
.d_records
.insert(dr
);
3297 dr
.d_place
= DNSResourceRecord::ANSWER
;
3298 dr
.d_name
= DNSName("test.powerdns.com.");
3299 dr
.d_type
= QType::NS
;
3301 dr
.d_content
= std::make_shared
<NSRecordContent
>(ns
);
3302 ad
.d_records
.insert(dr
);
3304 dr
.d_place
= DNSResourceRecord::ANSWER
;
3306 dr
.d_type
= QType::A
;
3308 dr
.d_content
= std::make_shared
<ARecordContent
>(nsAddr
);
3309 ad
.d_records
.insert(dr
);
3311 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3312 (*map
)[authZone
] = ad
;
3313 SyncRes::setDomainMap(map
);
3315 sr
->setAsyncCallback([&queriesCount
,nsAddr
,target
,targetAddr
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3319 if (ip
== ComboAddress(nsAddr
.toString(), 53) && domain
== target
) {
3320 setLWResult(res
, 0, true, false, true);
3321 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
3328 vector
<DNSRecord
> ret
;
3329 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3330 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3331 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3332 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3333 BOOST_CHECK_EQUAL(queriesCount
, 1);
3336 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard
) {
3337 std::unique_ptr
<SyncRes
> sr
;
3342 size_t queriesCount
= 0;
3343 const DNSName
target("test.powerdns.com.");
3344 const ComboAddress
targetAddr("192.0.2.2");
3345 const DNSName
authZone("powerdns.com");
3347 SyncRes::AuthDomain ad
;
3348 ad
.d_name
= authZone
;
3350 dr
.d_place
= DNSResourceRecord::ANSWER
;
3351 dr
.d_name
= authZone
;
3352 dr
.d_type
= QType::SOA
;
3354 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3355 ad
.d_records
.insert(dr
);
3357 dr
.d_place
= DNSResourceRecord::ANSWER
;
3358 dr
.d_name
= DNSName("*.powerdns.com.");
3359 dr
.d_type
= QType::A
;
3361 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3362 ad
.d_records
.insert(dr
);
3364 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3365 (*map
)[authZone
] = ad
;
3366 SyncRes::setDomainMap(map
);
3368 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3375 vector
<DNSRecord
> ret
;
3376 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3377 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3378 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3379 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3380 BOOST_CHECK_EQUAL(queriesCount
, 0);
3383 BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata
) {
3384 std::unique_ptr
<SyncRes
> sr
;
3389 size_t queriesCount
= 0;
3390 const DNSName
target("test.powerdns.com.");
3391 const ComboAddress
targetAddr("192.0.2.2");
3392 const DNSName
authZone("powerdns.com");
3394 SyncRes::AuthDomain ad
;
3395 ad
.d_name
= authZone
;
3397 dr
.d_place
= DNSResourceRecord::ANSWER
;
3398 dr
.d_name
= authZone
;
3399 dr
.d_type
= QType::SOA
;
3401 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3402 ad
.d_records
.insert(dr
);
3404 dr
.d_place
= DNSResourceRecord::ANSWER
;
3405 dr
.d_name
= DNSName("*.powerdns.com.");
3406 dr
.d_type
= QType::A
;
3408 dr
.d_content
= std::make_shared
<ARecordContent
>(targetAddr
);
3409 ad
.d_records
.insert(dr
);
3411 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3412 (*map
)[authZone
] = ad
;
3413 SyncRes::setDomainMap(map
);
3415 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3422 vector
<DNSRecord
> ret
;
3423 int res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
3424 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3425 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
3426 BOOST_CHECK(ret
[0].d_type
== QType::SOA
);
3427 BOOST_CHECK_EQUAL(queriesCount
, 0);
3430 BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only
) {
3431 std::unique_ptr
<SyncRes
> sr
;
3436 size_t queriesCount
= 0;
3437 const DNSName
target("powerdns.com.");
3438 const ComboAddress
addr("192.0.2.5");
3440 SyncRes::AuthDomain ad
;
3443 dr
.d_place
= DNSResourceRecord::ANSWER
;
3445 dr
.d_type
= QType::SOA
;
3447 dr
.d_content
= std::make_shared
<SOARecordContent
>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3448 ad
.d_records
.insert(dr
);
3450 dr
.d_place
= DNSResourceRecord::ANSWER
;
3452 dr
.d_type
= QType::A
;
3454 dr
.d_content
= std::make_shared
<ARecordContent
>(addr
);
3455 ad
.d_records
.insert(dr
);
3457 auto map
= std::make_shared
<SyncRes::domainmap_t
>();
3458 (*map
)[target
] = ad
;
3459 SyncRes::setDomainMap(map
);
3461 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3464 setLWResult(res
, 0, true, false, true);
3465 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
3469 /* simulate a no-RD query */
3472 vector
<DNSRecord
> ret
;
3473 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
3474 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3475 BOOST_CHECK_EQUAL(ret
.size(), 1);
3476 BOOST_CHECK(ret
[0].d_type
== QType::A
);
3477 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toString(), addr
.toString());
3478 BOOST_CHECK_EQUAL(queriesCount
, 0);
3481 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig
) {
3484 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3485 dcke
->create(dcke
->getBits());
3486 // cerr<<dcke->convertToISC()<<endl;
3487 DNSSECPrivateKey dpk
;
3491 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
3492 recordcontents
.push_back(getRecordContent(QType::A
, "192.0.2.1"));
3494 DNSName
qname("powerdns.com.");
3496 time_t now
= time(nullptr);
3497 RRSIGRecordContent rrc
;
3498 /* this RRSIG is valid for the current second only */
3499 computeRRSIG(dpk
, qname
, qname
, QType::A
, 600, 0, rrc
, recordcontents
, boost::none
, now
);
3502 keyset
.insert(std::make_shared
<DNSKEYRecordContent
>(dpk
.getDNSKEY()));
3504 std::vector
<std::shared_ptr
<RRSIGRecordContent
> > sigs
;
3505 sigs
.push_back(std::make_shared
<RRSIGRecordContent
>(rrc
));
3507 BOOST_CHECK(validateWithKeySet(now
, qname
, recordcontents
, sigs
, keyset
));
3510 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk
) {
3511 std::unique_ptr
<SyncRes
> sr
;
3514 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3517 const DNSName
target(".");
3520 auto luaconfsCopy
= g_luaconfs
.getCopy();
3521 luaconfsCopy
.dsAnchors
.clear();
3522 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3523 g_luaconfs
.setState(luaconfsCopy
);
3525 size_t queriesCount
= 0;
3527 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3530 if (domain
== target
&& type
== QType::NS
) {
3532 setLWResult(res
, 0, true, false, true);
3533 char addr
[] = "a.root-servers.net.";
3534 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3536 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3539 addRRSIG(keys
, res
->d_records
, domain
, 300);
3541 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3542 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3545 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3547 setLWResult(res
, 0, true, false, true);
3549 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3550 addRRSIG(keys
, res
->d_records
, domain
, 300);
3558 vector
<DNSRecord
> ret
;
3559 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3560 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3561 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3562 /* 13 NS + 1 RRSIG */
3563 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3564 BOOST_CHECK_EQUAL(queriesCount
, 2);
3566 /* again, to test the cache */
3568 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3569 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3570 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3571 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3572 BOOST_CHECK_EQUAL(queriesCount
, 2);
3575 BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk
) {
3576 std::unique_ptr
<SyncRes
> sr
;
3579 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3582 const DNSName
target(".");
3583 testkeysset_t zskeys
;
3584 testkeysset_t kskeys
;
3586 /* Generate key material for "." */
3587 auto dckeZ
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3588 dckeZ
->create(dckeZ
->getBits());
3589 DNSSECPrivateKey ksk
;
3592 DSRecordContent kskds
= makeDSFromDNSKey(target
, ksk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3594 auto dckeK
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3595 dckeK
->create(dckeK
->getBits());
3596 DNSSECPrivateKey zsk
;
3599 DSRecordContent zskds
= makeDSFromDNSKey(target
, zsk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3601 kskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(ksk
, kskds
);
3602 zskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(zsk
, zskds
);
3604 /* Set the root DS */
3605 auto luaconfsCopy
= g_luaconfs
.getCopy();
3606 luaconfsCopy
.dsAnchors
.clear();
3607 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(kskds
);
3608 g_luaconfs
.setState(luaconfsCopy
);
3610 size_t queriesCount
= 0;
3612 sr
->setAsyncCallback([target
,&queriesCount
,zskeys
,kskeys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3615 if (domain
== target
&& type
== QType::NS
) {
3617 setLWResult(res
, 0, true, false, true);
3618 char addr
[] = "a.root-servers.net.";
3619 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3621 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3624 addRRSIG(zskeys
, res
->d_records
, domain
, 300);
3626 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3627 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3630 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3632 setLWResult(res
, 0, true, false, true);
3634 addDNSKEY(kskeys
, domain
, 300, res
->d_records
);
3635 addDNSKEY(zskeys
, domain
, 300, res
->d_records
);
3636 addRRSIG(kskeys
, res
->d_records
, domain
, 300);
3644 vector
<DNSRecord
> ret
;
3645 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3646 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3647 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3648 /* 13 NS + 1 RRSIG */
3649 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3650 BOOST_CHECK_EQUAL(queriesCount
, 2);
3652 /* again, to test the cache */
3654 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3655 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3656 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
3657 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3658 BOOST_CHECK_EQUAL(queriesCount
, 2);
3661 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey
) {
3662 std::unique_ptr
<SyncRes
> sr
;
3665 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3668 const DNSName
target(".");
3671 auto luaconfsCopy
= g_luaconfs
.getCopy();
3672 luaconfsCopy
.dsAnchors
.clear();
3673 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3674 g_luaconfs
.setState(luaconfsCopy
);
3676 size_t queriesCount
= 0;
3678 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3681 if (domain
== target
&& type
== QType::NS
) {
3683 setLWResult(res
, 0, true, false, true);
3684 char addr
[] = "a.root-servers.net.";
3685 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3687 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3690 addRRSIG(keys
, res
->d_records
, domain
, 300);
3692 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3693 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3696 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3698 setLWResult(res
, 0, true, false, true);
3708 vector
<DNSRecord
> ret
;
3709 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3710 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3711 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3712 /* 13 NS + 1 RRSIG */
3713 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3714 BOOST_CHECK_EQUAL(queriesCount
, 2);
3716 /* again, to test the cache */
3718 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3719 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3720 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3721 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3722 BOOST_CHECK_EQUAL(queriesCount
, 2);
3725 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds
) {
3726 std::unique_ptr
<SyncRes
> sr
;
3729 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3732 const DNSName
target(".");
3733 testkeysset_t dskeys
;
3736 /* Generate key material for "." */
3737 auto dckeDS
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3738 dckeDS
->create(dckeDS
->getBits());
3739 DNSSECPrivateKey dskey
;
3740 dskey
.d_flags
= 257;
3741 dskey
.setKey(dckeDS
);
3742 DSRecordContent drc
= makeDSFromDNSKey(target
, dskey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3744 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3745 dcke
->create(dcke
->getBits());
3746 DNSSECPrivateKey dpk
;
3749 DSRecordContent uselessdrc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3751 dskeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dskey
, drc
);
3752 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, uselessdrc
);
3754 /* Set the root DS */
3755 auto luaconfsCopy
= g_luaconfs
.getCopy();
3756 luaconfsCopy
.dsAnchors
.clear();
3757 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3758 g_luaconfs
.setState(luaconfsCopy
);
3760 size_t queriesCount
= 0;
3762 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3765 if (domain
== target
&& type
== QType::NS
) {
3767 setLWResult(res
, 0, true, false, true);
3768 char addr
[] = "a.root-servers.net.";
3769 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3771 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3774 addRRSIG(keys
, res
->d_records
, domain
, 300);
3776 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3777 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3780 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3782 setLWResult(res
, 0, true, false, true);
3784 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3785 addRRSIG(keys
, res
->d_records
, domain
, 300);
3793 vector
<DNSRecord
> ret
;
3794 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3795 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3796 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3797 /* 13 NS + 1 RRSIG */
3798 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3799 BOOST_CHECK_EQUAL(queriesCount
, 2);
3801 /* again, to test the cache */
3803 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3804 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3805 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3806 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3807 BOOST_CHECK_EQUAL(queriesCount
, 2);
3810 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey
) {
3811 std::unique_ptr
<SyncRes
> sr
;
3814 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3817 const DNSName
target(".");
3819 testkeysset_t rrsigkeys
;
3821 auto luaconfsCopy
= g_luaconfs
.getCopy();
3822 luaconfsCopy
.dsAnchors
.clear();
3823 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3824 g_luaconfs
.setState(luaconfsCopy
);
3826 auto dckeRRSIG
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3827 dckeRRSIG
->create(dckeRRSIG
->getBits());
3828 DNSSECPrivateKey rrsigkey
;
3829 rrsigkey
.d_flags
= 257;
3830 rrsigkey
.setKey(dckeRRSIG
);
3831 DSRecordContent rrsigds
= makeDSFromDNSKey(target
, rrsigkey
.getDNSKEY(), DNSSECKeeper::SHA256
);
3833 rrsigkeys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(rrsigkey
, rrsigds
);
3835 size_t queriesCount
= 0;
3837 sr
->setAsyncCallback([target
,&queriesCount
,keys
,rrsigkeys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3840 if (domain
== target
&& type
== QType::NS
) {
3842 setLWResult(res
, 0, true, false, true);
3843 char addr
[] = "a.root-servers.net.";
3844 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3846 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3849 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3851 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3852 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3855 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3857 setLWResult(res
, 0, true, false, true);
3859 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3860 addRRSIG(rrsigkeys
, res
->d_records
, domain
, 300);
3868 vector
<DNSRecord
> ret
;
3869 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3870 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3871 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3872 /* 13 NS + 1 RRSIG */
3873 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3874 BOOST_CHECK_EQUAL(queriesCount
, 2);
3876 /* again, to test the cache */
3878 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3879 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3880 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3881 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
3882 BOOST_CHECK_EQUAL(queriesCount
, 2);
3885 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig
) {
3886 std::unique_ptr
<SyncRes
> sr
;
3889 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3892 const DNSName
target(".");
3895 auto luaconfsCopy
= g_luaconfs
.getCopy();
3896 luaconfsCopy
.dsAnchors
.clear();
3897 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
3898 g_luaconfs
.setState(luaconfsCopy
);
3900 size_t queriesCount
= 0;
3902 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3905 if (domain
== target
&& type
== QType::NS
) {
3907 setLWResult(res
, 0, true, false, true);
3908 char addr
[] = "a.root-servers.net.";
3909 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3911 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3916 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3917 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
3920 } else if (domain
== target
&& type
== QType::DNSKEY
) {
3922 setLWResult(res
, 0, true, false, true);
3924 addDNSKEY(keys
, domain
, 300, res
->d_records
);
3925 addRRSIG(keys
, res
->d_records
, domain
, 300);
3933 vector
<DNSRecord
> ret
;
3934 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3935 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3936 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3937 /* 13 NS + 0 RRSIG */
3938 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3939 /* no RRSIG so no query for DNSKEYs */
3940 BOOST_CHECK_EQUAL(queriesCount
, 1);
3942 /* again, to test the cache */
3944 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
3945 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
3946 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
3947 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
3948 BOOST_CHECK_EQUAL(queriesCount
, 1);
3951 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm
) {
3952 std::unique_ptr
<SyncRes
> sr
;
3955 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
3958 const DNSName
target(".");
3961 /* Generate key material for "." */
3962 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
3963 dcke
->create(dcke
->getBits());
3964 DNSSECPrivateKey dpk
;
3967 /* Fake algorithm number (private) */
3968 dpk
.d_algorithm
= 253;
3970 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
3971 keys
[target
] = std::pair
<DNSSECPrivateKey
,DSRecordContent
>(dpk
, drc
);
3972 /* Fake algorithm number (private) */
3973 drc
.d_algorithm
= 253;
3975 /* Set the root DS */
3976 auto luaconfsCopy
= g_luaconfs
.getCopy();
3977 luaconfsCopy
.dsAnchors
.clear();
3978 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
3979 g_luaconfs
.setState(luaconfsCopy
);
3981 size_t queriesCount
= 0;
3983 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
3986 if (domain
== target
&& type
== QType::NS
) {
3988 setLWResult(res
, 0, true, false, true);
3989 char addr
[] = "a.root-servers.net.";
3990 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
3992 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
3995 addRRSIG(keys
, res
->d_records
, domain
, 300);
3997 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
3998 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4001 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4003 setLWResult(res
, 0, true, false, true);
4005 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4006 addRRSIG(keys
, res
->d_records
, domain
, 300);
4014 vector
<DNSRecord
> ret
;
4015 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4016 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4017 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4018 /* 13 NS + 1 RRSIG */
4019 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4020 /* no supported DS so no query for DNSKEYs */
4021 BOOST_CHECK_EQUAL(queriesCount
, 1);
4023 /* again, to test the cache */
4025 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4026 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4027 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4028 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4029 BOOST_CHECK_EQUAL(queriesCount
, 1);
4032 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest
) {
4033 std::unique_ptr
<SyncRes
> sr
;
4036 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4039 const DNSName
target(".");
4042 /* Generate key material for "." */
4043 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256
));
4044 dcke
->create(dcke
->getBits());
4045 DNSSECPrivateKey dpk
;
4048 DSRecordContent drc
= makeDSFromDNSKey(target
, dpk
.getDNSKEY(), DNSSECKeeper::SHA256
);
4049 /* Fake digest number (reserved) */
4050 drc
.d_digesttype
= 0;
4052 keys
[target
] = std::pair
<DNSSECPrivateKey
, DSRecordContent
>(dpk
, drc
);
4054 /* Set the root DS */
4055 auto luaconfsCopy
= g_luaconfs
.getCopy();
4056 luaconfsCopy
.dsAnchors
.clear();
4057 luaconfsCopy
.dsAnchors
[g_rootdnsname
].insert(drc
);
4058 g_luaconfs
.setState(luaconfsCopy
);
4060 size_t queriesCount
= 0;
4062 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
4065 if (domain
== target
&& type
== QType::NS
) {
4067 setLWResult(res
, 0, true, false, true);
4068 char addr
[] = "a.root-servers.net.";
4069 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4071 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4074 addRRSIG(keys
, res
->d_records
, domain
, 300);
4076 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4077 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4080 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4082 setLWResult(res
, 0, true, false, true);
4084 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4085 addRRSIG(keys
, res
->d_records
, domain
, 300);
4093 vector
<DNSRecord
> ret
;
4094 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4095 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4096 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4097 /* 13 NS + 1 RRSIG */
4098 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4099 /* no supported DS so no query for DNSKEYs */
4100 BOOST_CHECK_EQUAL(queriesCount
, 1);
4102 /* again, to test the cache */
4104 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4105 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4106 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4107 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4108 BOOST_CHECK_EQUAL(queriesCount
, 1);
4111 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig
) {
4112 std::unique_ptr
<SyncRes
> sr
;
4115 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4118 const DNSName
target(".");
4121 auto luaconfsCopy
= g_luaconfs
.getCopy();
4122 luaconfsCopy
.dsAnchors
.clear();
4123 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4125 g_luaconfs
.setState(luaconfsCopy
);
4127 size_t queriesCount
= 0;
4129 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
4132 if (domain
== target
&& type
== QType::NS
) {
4134 setLWResult(res
, 0, true, false, true);
4135 char addr
[] = "a.root-servers.net.";
4136 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4138 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4141 addRRSIG(keys
, res
->d_records
, domain
, 300, true);
4143 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4144 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4147 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4149 setLWResult(res
, 0, true, false, true);
4151 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4152 addRRSIG(keys
, res
->d_records
, domain
, 300);
4160 vector
<DNSRecord
> ret
;
4161 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4162 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4163 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4164 /* 13 NS + 1 RRSIG */
4165 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4166 BOOST_CHECK_EQUAL(queriesCount
, 2);
4168 /* again, to test the cache */
4170 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4171 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4172 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4173 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4174 BOOST_CHECK_EQUAL(queriesCount
, 2);
4177 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo
) {
4178 std::unique_ptr
<SyncRes
> sr
;
4181 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4184 const DNSName
target(".");
4187 auto luaconfsCopy
= g_luaconfs
.getCopy();
4188 luaconfsCopy
.dsAnchors
.clear();
4189 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4191 g_luaconfs
.setState(luaconfsCopy
);
4193 size_t queriesCount
= 0;
4195 sr
->setAsyncCallback([target
,&queriesCount
,keys
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, std::shared_ptr
<RemoteLogger
> outgoingLogger
, LWResult
* res
, bool* chained
) {
4198 if (domain
== target
&& type
== QType::NS
) {
4200 setLWResult(res
, 0, true, false, true);
4201 char addr
[] = "a.root-servers.net.";
4202 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
4204 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
4207 /* FORCE WRONG ALGO */
4208 addRRSIG(keys
, res
->d_records
, domain
, 300, false, DNSSECKeeper::RSASHA256
);
4210 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
4211 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
4214 } else if (domain
== target
&& type
== QType::DNSKEY
) {
4216 setLWResult(res
, 0, true, false, true);
4218 addDNSKEY(keys
, domain
, 300, res
->d_records
);
4219 addRRSIG(keys
, res
->d_records
, domain
, 300);
4227 vector
<DNSRecord
> ret
;
4228 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4229 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4230 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4231 /* 13 NS + 1 RRSIG */
4232 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4233 BOOST_CHECK_EQUAL(queriesCount
, 2);
4235 /* again, to test the cache */
4237 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4238 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4239 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4240 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
4241 BOOST_CHECK_EQUAL(queriesCount
, 2);
4244 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds
) {
4245 std::unique_ptr
<SyncRes
> sr
;
4248 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4251 const DNSName
target("com.");
4252 const ComboAddress
targetAddr("192.0.2.42");
4255 auto luaconfsCopy
= g_luaconfs
.getCopy();
4256 luaconfsCopy
.dsAnchors
.clear();
4257 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4258 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4260 g_luaconfs
.setState(luaconfsCopy
);
4262 size_t queriesCount
= 0;
4264 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
) {
4267 DNSName auth
= domain
;
4269 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4270 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
) == 0) {
4274 if (type
== QType::DS
&& domain
== target
) {
4275 /* remove the last record, which is the DS's RRSIG */
4276 res
->d_records
.pop_back();
4282 if (isRootServer(ip
)) {
4283 setLWResult(res
, 0, false, false, true);
4284 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4285 /* Include the DS but omit the RRSIG*/
4286 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4287 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4291 if (ip
== ComboAddress("192.0.2.1:53")) {
4292 setLWResult(res
, RCode::NoError
, true, false, true);
4293 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4294 addRRSIG(keys
, res
->d_records
, auth
, 300);
4301 vector
<DNSRecord
> ret
;
4302 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4303 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4304 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4305 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4306 BOOST_CHECK_EQUAL(queriesCount
, 4);
4308 /* again, to test the cache */
4310 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4311 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4312 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4313 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4314 BOOST_CHECK_EQUAL(queriesCount
, 4);
4316 /* now we ask directly for the DS */
4318 res
= sr
->beginResolve(DNSName("com."), QType(QType::DS
), QClass::IN
, ret
);
4319 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4320 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4321 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4322 BOOST_CHECK_EQUAL(queriesCount
, 4);
4325 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds_direct
) {
4326 std::unique_ptr
<SyncRes
> sr
;
4329 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4332 const DNSName
target("com.");
4335 auto luaconfsCopy
= g_luaconfs
.getCopy();
4336 luaconfsCopy
.dsAnchors
.clear();
4337 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4338 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4340 g_luaconfs
.setState(luaconfsCopy
);
4342 size_t queriesCount
= 0;
4344 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
) {
4347 DNSName auth
= domain
;
4349 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4350 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
) == 0) {
4354 if (type
== QType::DS
&& domain
== target
) {
4355 /* remove the last record, which is the DS's RRSIG */
4356 res
->d_records
.pop_back();
4362 if (isRootServer(ip
)) {
4363 setLWResult(res
, 0, false, false, true);
4364 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4365 /* Include the DS but omit the RRSIG*/
4366 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4367 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4374 vector
<DNSRecord
> ret
;
4375 int res
= sr
->beginResolve(DNSName("com."), QType(QType::DS
), QClass::IN
, ret
);
4376 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4377 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
4378 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4379 BOOST_CHECK_EQUAL(queriesCount
, 1);
4382 BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos
) {
4383 std::unique_ptr
<SyncRes
> sr
;
4386 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4389 const DNSName
target("powerdns.com.");
4390 const ComboAddress
targetAddr("192.0.2.42");
4393 auto luaconfsCopy
= g_luaconfs
.getCopy();
4394 luaconfsCopy
.dsAnchors
.clear();
4395 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::RSASHA512
, DNSSECKeeper::SHA384
, keys
, luaconfsCopy
.dsAnchors
);
4396 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4397 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384
, DNSSECKeeper::SHA384
, keys
);
4399 g_luaconfs
.setState(luaconfsCopy
);
4401 size_t queriesCount
= 0;
4403 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
) {
4406 DNSName auth
= domain
;
4407 if (domain
== target
) {
4408 auth
= DNSName("powerdns.com.");
4411 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4412 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4415 if (isRootServer(ip
)) {
4416 setLWResult(res
, 0, false, false, true);
4417 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4418 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4419 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4420 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4424 if (ip
== ComboAddress("192.0.2.1:53")) {
4425 if (domain
== DNSName("com.")) {
4426 setLWResult(res
, 0, true, false, true);
4427 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4428 addRRSIG(keys
, res
->d_records
, domain
, 300);
4429 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4430 addRRSIG(keys
, res
->d_records
, domain
, 300);
4433 setLWResult(res
, 0, false, false, true);
4434 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4435 addDS(auth
, 300, res
->d_records
, keys
);
4436 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4437 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4442 if (ip
== ComboAddress("192.0.2.2:53")) {
4443 if (type
== QType::NS
) {
4444 setLWResult(res
, 0, true, false, true);
4445 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4446 addRRSIG(keys
, res
->d_records
, auth
, 300);
4447 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4448 addRRSIG(keys
, res
->d_records
, auth
, 300);
4451 setLWResult(res
, RCode::NoError
, true, false, true);
4452 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4453 addRRSIG(keys
, res
->d_records
, auth
, 300);
4461 vector
<DNSRecord
> ret
;
4462 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4463 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4464 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4465 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4466 BOOST_CHECK_EQUAL(queriesCount
, 8);
4468 /* again, to test the cache */
4470 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4471 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4472 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4473 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4474 BOOST_CHECK_EQUAL(queriesCount
, 8);
4477 BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns
) {
4478 std::unique_ptr
<SyncRes
> sr
;
4481 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4484 const DNSName
target("powerdns.com.");
4485 const ComboAddress
targetAddr("192.0.2.42");
4488 auto luaconfsCopy
= g_luaconfs
.getCopy();
4489 luaconfsCopy
.dsAnchors
.clear();
4490 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4491 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4492 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4493 g_luaconfs
.setState(luaconfsCopy
);
4495 size_t queriesCount
= 0;
4497 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
) {
4500 DNSName auth
= domain
;
4501 if (domain
== target
) {
4502 auth
= DNSName("powerdns.com.");
4505 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4506 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4509 if (isRootServer(ip
)) {
4510 setLWResult(res
, 0, false, false, true);
4511 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4512 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4513 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4514 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4518 if (ip
== ComboAddress("192.0.2.1:53")) {
4519 if (domain
== DNSName("com.")) {
4520 setLWResult(res
, 0, true, false, true);
4521 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4522 addRRSIG(keys
, res
->d_records
, domain
, 300);
4523 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4524 addRRSIG(keys
, res
->d_records
, domain
, 300);
4527 setLWResult(res
, 0, false, false, true);
4528 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4529 addDS(auth
, 300, res
->d_records
, keys
);
4530 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4531 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4536 if (ip
== ComboAddress("192.0.2.2:53")) {
4537 if (type
== QType::NS
) {
4538 setLWResult(res
, 0, true, false, true);
4539 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4540 addRRSIG(keys
, res
->d_records
, auth
, 300);
4541 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4542 addRRSIG(keys
, res
->d_records
, auth
, 300);
4545 setLWResult(res
, RCode::NoError
, true, false, true);
4546 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4547 addRRSIG(keys
, res
->d_records
, auth
, 300);
4555 vector
<DNSRecord
> ret
;
4556 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4557 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4558 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4559 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4560 BOOST_CHECK_EQUAL(queriesCount
, 8);
4562 /* again, to test the cache */
4564 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4565 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4566 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4567 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4568 BOOST_CHECK_EQUAL(queriesCount
, 8);
4570 /* this time we ask for the NS that should be in the cache, to check
4571 the validation status */
4573 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4574 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4575 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4576 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4577 BOOST_CHECK_EQUAL(queriesCount
, 9);
4581 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns
) {
4582 std::unique_ptr
<SyncRes
> sr
;
4585 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4588 const DNSName
target("powerdns.com.");
4589 const ComboAddress
targetAddr("192.0.2.42");
4592 auto luaconfsCopy
= g_luaconfs
.getCopy();
4593 luaconfsCopy
.dsAnchors
.clear();
4594 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4595 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4596 g_luaconfs
.setState(luaconfsCopy
);
4598 size_t queriesCount
= 0;
4600 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
) {
4603 DNSName auth
= domain
;
4604 if (domain
== target
) {
4605 auth
= DNSName("powerdns.com.");
4608 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4609 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4612 if (isRootServer(ip
)) {
4613 setLWResult(res
, 0, false, false, true);
4614 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4615 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4616 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4617 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4621 if (ip
== ComboAddress("192.0.2.1:53")) {
4622 if (domain
== DNSName("com.")) {
4623 setLWResult(res
, 0, true, false, true);
4624 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4625 addRRSIG(keys
, res
->d_records
, domain
, 300);
4626 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4627 addRRSIG(keys
, res
->d_records
, domain
, 300);
4630 setLWResult(res
, 0, false, false, true);
4631 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4633 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
4634 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4635 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4640 if (ip
== ComboAddress("192.0.2.2:53")) {
4641 if (type
== QType::NS
) {
4642 setLWResult(res
, 0, true, false, true);
4643 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4644 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4647 setLWResult(res
, RCode::NoError
, true, false, true);
4648 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4656 vector
<DNSRecord
> ret
;
4657 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4658 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4659 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4660 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4661 BOOST_CHECK_EQUAL(queriesCount
, 7);
4663 /* again, to test the cache */
4665 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4666 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4667 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4668 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4669 BOOST_CHECK_EQUAL(queriesCount
, 7);
4671 /* this time we ask for the NS that should be in the cache, to check
4672 the validation status */
4674 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
4675 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4676 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4677 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4678 BOOST_CHECK_EQUAL(queriesCount
, 8);
4681 BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta
) {
4682 std::unique_ptr
<SyncRes
> sr
;
4685 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4688 const DNSName
target("powerdns.com.");
4689 const ComboAddress
targetAddr("192.0.2.42");
4692 auto luaconfsCopy
= g_luaconfs
.getCopy();
4693 luaconfsCopy
.dsAnchors
.clear();
4694 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4695 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4696 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4698 /* Add a NTA for "powerdns.com" */
4699 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4701 g_luaconfs
.setState(luaconfsCopy
);
4703 size_t queriesCount
= 0;
4705 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
) {
4708 DNSName auth
= domain
;
4709 if (domain
== target
) {
4710 auth
= DNSName("powerdns.com.");
4713 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4714 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4717 if (isRootServer(ip
)) {
4718 setLWResult(res
, 0, false, false, true);
4719 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4720 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4721 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4722 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4726 if (ip
== ComboAddress("192.0.2.1:53")) {
4727 if (domain
== DNSName("com.")) {
4728 setLWResult(res
, 0, true, false, true);
4729 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4730 addRRSIG(keys
, res
->d_records
, domain
, 300);
4731 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4732 addRRSIG(keys
, res
->d_records
, domain
, 300);
4735 setLWResult(res
, 0, false, false, true);
4736 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4737 addDS(auth
, 300, res
->d_records
, keys
);
4738 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4739 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4744 if (ip
== ComboAddress("192.0.2.2:53")) {
4745 if (type
== QType::NS
) {
4746 setLWResult(res
, 0, true, false, true);
4747 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4748 addRRSIG(keys
, res
->d_records
, auth
, 300);
4749 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4750 addRRSIG(keys
, res
->d_records
, auth
, 300);
4753 setLWResult(res
, RCode::NoError
, true, false, true);
4754 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4755 addRRSIG(keys
, res
->d_records
, auth
, 300);
4763 vector
<DNSRecord
> ret
;
4764 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4765 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4766 /* Should be insecure because of the NTA */
4767 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4768 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4769 BOOST_CHECK_EQUAL(queriesCount
, 5);
4771 /* again, to test the cache */
4773 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4774 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4775 /* Should be insecure because of the NTA */
4776 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4777 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
4778 BOOST_CHECK_EQUAL(queriesCount
, 5);
4781 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta
) {
4782 std::unique_ptr
<SyncRes
> sr
;
4785 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4788 const DNSName
target("powerdns.com.");
4789 const ComboAddress
targetAddr("192.0.2.42");
4792 auto luaconfsCopy
= g_luaconfs
.getCopy();
4793 luaconfsCopy
.dsAnchors
.clear();
4794 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4795 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4796 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4798 /* Add a NTA for "powerdns.com" */
4799 luaconfsCopy
.negAnchors
[target
] = "NTA for PowerDNS.com";
4801 g_luaconfs
.setState(luaconfsCopy
);
4803 size_t queriesCount
= 0;
4805 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
) {
4808 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4809 setLWResult(res
, 0, false, false, true);
4810 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4814 if (isRootServer(ip
)) {
4815 setLWResult(res
, 0, false, false, true);
4816 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4817 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4820 else if (ip
== ComboAddress("192.0.2.1:53")) {
4821 if (domain
== DNSName("com.")) {
4822 setLWResult(res
, 0, true, false, true);
4823 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4824 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4827 setLWResult(res
, 0, false, false, true);
4828 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4829 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4833 else 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 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4840 setLWResult(res
, RCode::NoError
, true, false, true);
4841 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
4850 /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
4851 vector
<DNSRecord
> ret
;
4852 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4853 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4854 /* Should be insecure because of the NTA */
4855 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4856 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4857 BOOST_CHECK_EQUAL(queriesCount
, 4);
4859 /* again, to test the cache */
4861 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4862 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4863 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
4864 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
4865 BOOST_CHECK_EQUAL(queriesCount
, 4);
4868 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec
) {
4869 std::unique_ptr
<SyncRes
> sr
;
4872 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4875 const DNSName
target("powerdns.com.");
4878 auto luaconfsCopy
= g_luaconfs
.getCopy();
4879 luaconfsCopy
.dsAnchors
.clear();
4880 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4881 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4882 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4884 g_luaconfs
.setState(luaconfsCopy
);
4886 size_t queriesCount
= 0;
4888 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
) {
4891 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4892 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
4895 if (isRootServer(ip
)) {
4896 setLWResult(res
, 0, false, false, true);
4897 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
4898 addDS(DNSName("com."), 300, res
->d_records
, keys
);
4899 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
4900 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4903 else if (ip
== ComboAddress("192.0.2.1:53")) {
4904 if (domain
== DNSName("com.")) {
4905 setLWResult(res
, 0, true, false, true);
4906 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
4907 addRRSIG(keys
, res
->d_records
, domain
, 300);
4908 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
4909 addRRSIG(keys
, res
->d_records
, domain
, 300);
4912 setLWResult(res
, 0, false, false, true);
4913 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
4914 addDS(domain
, 300, res
->d_records
, keys
);
4915 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
4916 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4920 else if (ip
== ComboAddress("192.0.2.2:53")) {
4921 if (type
== QType::NS
) {
4922 setLWResult(res
, 0, true, false, true);
4923 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
4924 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4925 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
4926 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
4929 setLWResult(res
, 0, true, false, true);
4930 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4931 addRRSIG(keys
, res
->d_records
, domain
, 300);
4932 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
4933 addRRSIG(keys
, res
->d_records
, domain
, 300);
4942 vector
<DNSRecord
> ret
;
4943 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4944 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4945 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4946 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4947 BOOST_CHECK_EQUAL(queriesCount
, 8);
4949 /* again, to test the cache */
4951 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
4952 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
4953 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
4954 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
4955 BOOST_CHECK_EQUAL(queriesCount
, 8);
4958 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec
) {
4959 std::unique_ptr
<SyncRes
> sr
;
4962 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
4965 const DNSName
target("nx.powerdns.com.");
4968 auto luaconfsCopy
= g_luaconfs
.getCopy();
4969 luaconfsCopy
.dsAnchors
.clear();
4970 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
4971 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4972 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
4974 g_luaconfs
.setState(luaconfsCopy
);
4976 size_t queriesCount
= 0;
4978 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
) {
4981 DNSName auth
= domain
;
4982 if (domain
== target
) {
4983 auth
= DNSName("powerdns.com.");
4985 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
4986 if (type
== QType::DS
&& domain
== target
) {
4987 setLWResult(res
, RCode::NXDomain
, true, false, true);
4988 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
4989 addRRSIG(keys
, res
->d_records
, auth
, 300);
4990 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
4991 addRRSIG(keys
, res
->d_records
, auth
, 300);
4995 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
4999 if (isRootServer(ip
)) {
5000 setLWResult(res
, 0, false, false, true);
5001 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5002 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5003 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5004 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5007 else if (ip
== ComboAddress("192.0.2.1:53")) {
5008 if (domain
== DNSName("com.")) {
5009 setLWResult(res
, 0, true, false, true);
5010 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5011 addRRSIG(keys
, res
->d_records
, domain
, 300);
5012 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5013 addRRSIG(keys
, res
->d_records
, domain
, 300);
5016 setLWResult(res
, 0, false, false, true);
5017 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5018 addDS(auth
, 300, res
->d_records
, keys
);
5019 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5020 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5024 else if (ip
== ComboAddress("192.0.2.2:53")) {
5025 if (type
== QType::NS
) {
5026 setLWResult(res
, 0, true, false, true);
5027 if (domain
== DNSName("powerdns.com.")) {
5028 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5029 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5030 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5031 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5034 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5035 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5036 addNSECRecordToLW(DNSName("nx.powerdns.com."), DNSName("nz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5037 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5041 setLWResult(res
, RCode::NXDomain
, true, false, true);
5042 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5043 addRRSIG(keys
, res
->d_records
, auth
, 300);
5044 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5045 addRRSIG(keys
, res
->d_records
, auth
, 300);
5046 /* add wildcard denial */
5047 addNSECRecordToLW(DNSName("powerdns.com."), DNSName("a.powerdns.com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5048 addRRSIG(keys
, res
->d_records
, auth
, 300);
5057 vector
<DNSRecord
> ret
;
5058 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5059 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
5060 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5061 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5062 BOOST_CHECK_EQUAL(queriesCount
, 9);
5064 /* again, to test the cache */
5066 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5067 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
5068 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5069 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5070 BOOST_CHECK_EQUAL(queriesCount
, 9);
5073 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard
) {
5074 std::unique_ptr
<SyncRes
> sr
;
5077 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5080 const DNSName
target("www.powerdns.com.");
5083 auto luaconfsCopy
= g_luaconfs
.getCopy();
5084 luaconfsCopy
.dsAnchors
.clear();
5085 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5086 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5087 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5089 g_luaconfs
.setState(luaconfsCopy
);
5091 size_t queriesCount
= 0;
5093 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
) {
5096 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5097 if (type
== QType::DS
&& domain
== target
) {
5098 setLWResult(res
, RCode::NoError
, true, false, true);
5099 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5100 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5101 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5102 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5106 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5110 if (isRootServer(ip
)) {
5111 setLWResult(res
, 0, false, false, true);
5112 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5113 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5114 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5115 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5118 else if (ip
== ComboAddress("192.0.2.1:53")) {
5119 if (domain
== DNSName("com.")) {
5120 setLWResult(res
, 0, true, false, true);
5121 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5122 addRRSIG(keys
, res
->d_records
, domain
, 300);
5123 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5124 addRRSIG(keys
, res
->d_records
, domain
, 300);
5127 setLWResult(res
, 0, false, false, true);
5128 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5129 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5130 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5131 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5135 else if (ip
== ComboAddress("192.0.2.2:53")) {
5136 setLWResult(res
, 0, true, false, true);
5137 if (type
== QType::NS
) {
5138 if (domain
== DNSName("powerdns.com.")) {
5139 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5140 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5141 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5142 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5145 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5146 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5147 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5148 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5152 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5153 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5154 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5155 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5156 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5165 vector
<DNSRecord
> ret
;
5166 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5167 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5168 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5169 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5170 BOOST_CHECK_EQUAL(queriesCount
, 9);
5172 /* again, to test the cache */
5174 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5175 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5176 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5177 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
5178 BOOST_CHECK_EQUAL(queriesCount
, 9);
5181 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_nodata_nowildcard
) {
5182 std::unique_ptr
<SyncRes
> sr
;
5185 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5188 const DNSName
target("www.com.");
5191 auto luaconfsCopy
= g_luaconfs
.getCopy();
5192 luaconfsCopy
.dsAnchors
.clear();
5193 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5194 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5196 g_luaconfs
.setState(luaconfsCopy
);
5198 size_t queriesCount
= 0;
5200 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
) {
5203 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5204 if (type
== QType::DS
&& domain
== target
) {
5205 DNSName
auth("com.");
5206 setLWResult(res
, 0, true, false, true);
5208 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5209 addRRSIG(keys
, res
->d_records
, auth
, 300);
5210 /* add a NSEC denying the DS AND the existence of a cut (no NS) */
5211 addNSECRecordToLW(domain
, DNSName("z") + domain
, { QType::NSEC
}, 600, res
->d_records
);
5212 addRRSIG(keys
, res
->d_records
, auth
, 300);
5215 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5218 if (isRootServer(ip
)) {
5219 setLWResult(res
, 0, false, false, true);
5220 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5221 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5222 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5223 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5226 else if (ip
== ComboAddress("192.0.2.1:53")) {
5227 setLWResult(res
, 0, true, false, true);
5229 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5230 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5231 /* no record for this name */
5232 addNSECRecordToLW(DNSName("wwv.com."), DNSName("wwx.com."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5233 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5234 /* a wildcard matches but has no record for this type */
5235 addNSECRecordToLW(DNSName("*.com."), DNSName("com."), { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5236 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5244 vector
<DNSRecord
> ret
;
5245 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5246 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5247 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5248 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5249 BOOST_CHECK_EQUAL(queriesCount
, 6);
5251 /* again, to test the cache */
5253 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5254 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5255 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5256 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5257 BOOST_CHECK_EQUAL(queriesCount
, 6);
5260 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard
) {
5261 std::unique_ptr
<SyncRes
> sr
;
5264 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5267 const DNSName
target("www.com.");
5270 auto luaconfsCopy
= g_luaconfs
.getCopy();
5271 luaconfsCopy
.dsAnchors
.clear();
5272 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5273 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5275 g_luaconfs
.setState(luaconfsCopy
);
5277 size_t queriesCount
= 0;
5279 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
) {
5282 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5283 if (type
== QType::DS
&& domain
== target
) {
5284 DNSName
auth("com.");
5285 setLWResult(res
, 0, true, false, true);
5287 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5288 addRRSIG(keys
, res
->d_records
, auth
, 300);
5289 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5290 /* first the closest encloser */
5291 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5292 addRRSIG(keys
, res
->d_records
, auth
, 300);
5293 /* then the next closer */
5294 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5295 addRRSIG(keys
, res
->d_records
, auth
, 300);
5296 /* a wildcard matches but has no record for this type */
5297 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5298 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5301 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5304 if (isRootServer(ip
)) {
5305 setLWResult(res
, 0, false, false, true);
5306 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5307 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5308 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5309 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5312 else if (ip
== ComboAddress("192.0.2.1:53")) {
5313 setLWResult(res
, 0, true, false, true);
5315 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5316 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5317 /* no record for this name */
5318 /* first the closest encloser */
5319 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5320 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5321 /* then the next closer */
5322 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5323 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5324 /* a wildcard matches but has no record for this type */
5325 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5326 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5334 vector
<DNSRecord
> ret
;
5335 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5336 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5337 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5338 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5339 BOOST_CHECK_EQUAL(queriesCount
, 6);
5341 /* again, to test the cache */
5343 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5344 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5345 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5346 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5347 BOOST_CHECK_EQUAL(queriesCount
, 6);
5350 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_too_many_iterations
) {
5351 std::unique_ptr
<SyncRes
> sr
;
5354 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5357 const DNSName
target("www.com.");
5360 auto luaconfsCopy
= g_luaconfs
.getCopy();
5361 luaconfsCopy
.dsAnchors
.clear();
5362 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5363 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5365 g_luaconfs
.setState(luaconfsCopy
);
5367 size_t queriesCount
= 0;
5369 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
) {
5372 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5373 if (type
== QType::DS
&& domain
== target
) {
5374 DNSName
auth("com.");
5375 setLWResult(res
, 0, true, false, true);
5377 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5378 addRRSIG(keys
, res
->d_records
, auth
, 300);
5379 /* add a NSEC3 denying the DS AND the existence of a cut (no NS) */
5380 /* first the closest encloser */
5381 addNSEC3UnhashedRecordToLW(DNSName("com."), auth
, "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5382 addRRSIG(keys
, res
->d_records
, auth
, 300);
5383 /* then the next closer */
5384 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5385 addRRSIG(keys
, res
->d_records
, auth
, 300);
5386 /* a wildcard matches but has no record for this type */
5387 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5388 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5391 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5394 if (isRootServer(ip
)) {
5395 setLWResult(res
, 0, false, false, true);
5396 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5397 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5398 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5399 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5402 else if (ip
== ComboAddress("192.0.2.1:53")) {
5403 setLWResult(res
, 0, true, false, true);
5405 addRecordToLW(res
, DNSName("com."), QType::SOA
, "com. com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5406 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5407 /* no record for this name */
5408 /* first the closest encloser */
5409 addNSEC3UnhashedRecordToLW(DNSName("com."), DNSName("com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5410 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5411 /* then the next closer */
5412 addNSEC3NarrowRecordToLW(domain
, DNSName("com."), { QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5413 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5414 /* a wildcard matches but has no record for this type */
5415 addNSEC3UnhashedRecordToLW(DNSName("*.com."), DNSName("com."), "whatever", { QType::AAAA
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5416 addRRSIG(keys
, res
->d_records
, DNSName("com"), 300, false, boost::none
, DNSName("*.com"));
5424 /* we are generating NSEC3 with more iterations than we allow, so we should go Insecure */
5425 vector
<DNSRecord
> ret
;
5426 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5427 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5428 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5429 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5430 BOOST_CHECK_EQUAL(queriesCount
, 6);
5432 /* again, to test the cache */
5434 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5435 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5436 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5437 BOOST_REQUIRE_EQUAL(ret
.size(), 8);
5438 BOOST_CHECK_EQUAL(queriesCount
, 6);
5441 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard
) {
5442 std::unique_ptr
<SyncRes
> sr
;
5445 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5448 const DNSName
target("www.sub.powerdns.com.");
5451 auto luaconfsCopy
= g_luaconfs
.getCopy();
5452 luaconfsCopy
.dsAnchors
.clear();
5453 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5454 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5455 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5457 g_luaconfs
.setState(luaconfsCopy
);
5459 size_t queriesCount
= 0;
5461 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
) {
5464 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5465 if (type
== QType::DS
&& domain
.isPartOf(DNSName("sub.powerdns.com"))) {
5466 setLWResult(res
, RCode::NoError
, true, false, true);
5467 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5468 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5469 if (domain
== DNSName("sub.powerdns.com")) {
5470 addNSECRecordToLW(DNSName("sub.powerdns.com."), DNSName("sud.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5472 else if (domain
== target
) {
5473 addNSECRecordToLW(DNSName("www.sub.powerdns.com."), DNSName("wwz.sub.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5475 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5479 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 if (domain
== DNSName("com.")) {
5493 setLWResult(res
, 0, true, false, true);
5494 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5495 addRRSIG(keys
, res
->d_records
, domain
, 300);
5496 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5497 addRRSIG(keys
, res
->d_records
, domain
, 300);
5500 setLWResult(res
, 0, false, false, true);
5501 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5502 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5503 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5504 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5508 else if (ip
== ComboAddress("192.0.2.2:53")) {
5509 setLWResult(res
, 0, true, false, true);
5510 if (type
== QType::NS
) {
5511 if (domain
== DNSName("powerdns.com.")) {
5512 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5513 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5514 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5515 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5518 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5519 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5520 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5521 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5525 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5526 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5527 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5528 /* first the closest encloser */
5529 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5530 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5531 /* then the next closer */
5532 addNSEC3NarrowRecordToLW(DNSName("sub.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5533 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5542 vector
<DNSRecord
> ret
;
5543 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5544 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5545 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5546 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5547 BOOST_CHECK_EQUAL(queriesCount
, 10);
5549 /* again, to test the cache */
5551 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5552 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5553 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5554 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5555 BOOST_CHECK_EQUAL(queriesCount
, 10);
5558 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard_too_many_iterations
) {
5559 std::unique_ptr
<SyncRes
> sr
;
5562 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5565 const DNSName
target("www.powerdns.com.");
5568 auto luaconfsCopy
= g_luaconfs
.getCopy();
5569 luaconfsCopy
.dsAnchors
.clear();
5570 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5571 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5572 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5574 g_luaconfs
.setState(luaconfsCopy
);
5576 size_t queriesCount
= 0;
5578 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
) {
5581 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5582 if (type
== QType::DS
&& domain
== target
) {
5583 setLWResult(res
, RCode::NoError
, true, false, true);
5584 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5585 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5586 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5587 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5591 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5595 if (isRootServer(ip
)) {
5596 setLWResult(res
, 0, false, false, true);
5597 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5598 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5599 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5600 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5603 else if (ip
== ComboAddress("192.0.2.1:53")) {
5604 if (domain
== DNSName("com.")) {
5605 setLWResult(res
, 0, true, false, true);
5606 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5607 addRRSIG(keys
, res
->d_records
, domain
, 300);
5608 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5609 addRRSIG(keys
, res
->d_records
, domain
, 300);
5612 setLWResult(res
, 0, false, false, true);
5613 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5614 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5615 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5616 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5620 else if (ip
== ComboAddress("192.0.2.2:53")) {
5621 setLWResult(res
, 0, true, false, true);
5622 if (type
== QType::NS
) {
5623 if (domain
== DNSName("powerdns.com.")) {
5624 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5625 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5626 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5627 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5630 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5631 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5632 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5633 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5637 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5638 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5639 /* we need to add the proof that this name does not exist, so the wildcard may apply */
5640 /* first the closest encloser */
5641 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
5642 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5643 /* then the next closer */
5644 addNSEC3NarrowRecordToLW(DNSName("www.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
, g_maxNSEC3Iterations
+ 100);
5645 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5654 /* the NSEC3 providing the denial of existence proof for the next closer has too many iterations,
5655 we should end up Insecure */
5656 vector
<DNSRecord
> ret
;
5657 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5658 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5659 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5660 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5661 BOOST_CHECK_EQUAL(queriesCount
, 9);
5663 /* again, to test the cache */
5665 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5666 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5667 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
5668 BOOST_REQUIRE_EQUAL(ret
.size(), 6);
5669 BOOST_CHECK_EQUAL(queriesCount
, 9);
5672 BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_missing
) {
5673 std::unique_ptr
<SyncRes
> sr
;
5676 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5679 const DNSName
target("www.powerdns.com.");
5682 auto luaconfsCopy
= g_luaconfs
.getCopy();
5683 luaconfsCopy
.dsAnchors
.clear();
5684 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5685 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5686 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5688 g_luaconfs
.setState(luaconfsCopy
);
5690 size_t queriesCount
= 0;
5692 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
) {
5695 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
5696 if (type
== QType::DS
&& domain
== target
) {
5697 setLWResult(res
, RCode::NoError
, true, false, true);
5698 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5699 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
5700 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5701 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5705 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
5709 if (isRootServer(ip
)) {
5710 setLWResult(res
, 0, false, false, true);
5711 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5712 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5713 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5714 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5717 else if (ip
== ComboAddress("192.0.2.1:53")) {
5718 if (domain
== DNSName("com.")) {
5719 setLWResult(res
, 0, true, false, true);
5720 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5721 addRRSIG(keys
, res
->d_records
, domain
, 300);
5722 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5723 addRRSIG(keys
, res
->d_records
, domain
, 300);
5726 setLWResult(res
, 0, false, false, true);
5727 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5728 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
5729 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5730 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5734 else if (ip
== ComboAddress("192.0.2.2:53")) {
5735 setLWResult(res
, 0, true, false, true);
5736 if (type
== QType::NS
) {
5737 if (domain
== DNSName("powerdns.com.")) {
5738 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5739 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5740 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5741 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5744 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5745 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5746 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5747 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5751 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5752 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300, false, boost::none
, DNSName("*.powerdns.com"));
5761 vector
<DNSRecord
> ret
;
5762 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5763 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5764 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5765 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5766 BOOST_CHECK_EQUAL(queriesCount
, 9);
5768 /* again, to test the cache */
5770 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5771 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5772 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5773 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5774 BOOST_CHECK_EQUAL(queriesCount
, 9);
5777 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure
) {
5778 std::unique_ptr
<SyncRes
> sr
;
5781 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5784 const DNSName
target("www.powerdns.com.");
5787 auto luaconfsCopy
= g_luaconfs
.getCopy();
5788 luaconfsCopy
.dsAnchors
.clear();
5789 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5790 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5791 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5793 g_luaconfs
.setState(luaconfsCopy
);
5795 size_t queriesCount
= 0;
5796 size_t dsQueriesCount
= 0;
5798 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
) {
5801 if (type
== QType::DS
) {
5802 DNSName
auth(domain
);
5806 setLWResult(res
, 0, true, false, true);
5807 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5808 addRRSIG(keys
, res
->d_records
, auth
, 300);
5811 else if (type
== QType::DNSKEY
) {
5812 setLWResult(res
, 0, true, false, true);
5813 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5814 addRRSIG(keys
, res
->d_records
, domain
, 300);
5818 if (isRootServer(ip
)) {
5819 setLWResult(res
, 0, false, false, true);
5820 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5821 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5822 /* No DS on referral, and no denial of the DS either */
5825 else if (ip
== ComboAddress("192.0.2.1:53")) {
5826 if (domain
== DNSName("com.")) {
5827 setLWResult(res
, 0, true, false, true);
5828 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5829 addRRSIG(keys
, res
->d_records
, domain
, 300);
5830 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5831 addRRSIG(keys
, res
->d_records
, domain
, 300);
5834 setLWResult(res
, 0, false, false, true);
5835 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5836 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5837 /* No DS on referral, and no denial of the DS either */
5841 else if (ip
== ComboAddress("192.0.2.2:53")) {
5842 setLWResult(res
, 0, true, false, true);
5843 if (type
== QType::NS
) {
5844 if (domain
== DNSName("powerdns.com.")) {
5845 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5846 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5847 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5848 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5851 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
5852 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5853 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A
, QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
5854 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5858 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5859 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
5869 vector
<DNSRecord
> ret
;
5870 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5871 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5872 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5873 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5874 BOOST_CHECK_EQUAL(queriesCount
, 9);
5875 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5877 /* again, to test the cache */
5879 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5880 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5881 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
5882 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5883 BOOST_CHECK_EQUAL(queriesCount
, 9);
5884 BOOST_CHECK_EQUAL(dsQueriesCount
, 3);
5887 BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop
) {
5888 std::unique_ptr
<SyncRes
> sr
;
5891 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
5894 const DNSName
target("www.powerdns.com.");
5897 auto luaconfsCopy
= g_luaconfs
.getCopy();
5898 luaconfsCopy
.dsAnchors
.clear();
5899 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
5900 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5901 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5902 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
5904 g_luaconfs
.setState(luaconfsCopy
);
5906 size_t queriesCount
= 0;
5908 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
) {
5911 if (type
== QType::DS
) {
5912 DNSName
auth(domain
);
5915 setLWResult(res
, 0, true, false, true);
5916 if (domain
== target
) {
5917 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
5918 addRRSIG(keys
, res
->d_records
, target
, 300);
5921 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
5922 addRRSIG(keys
, res
->d_records
, auth
, 300);
5926 else if (type
== QType::DNSKEY
) {
5927 setLWResult(res
, 0, true, false, true);
5928 addDNSKEY(keys
, domain
, 300, res
->d_records
);
5929 addRRSIG(keys
, res
->d_records
, domain
, 300);
5933 if (isRootServer(ip
)) {
5934 setLWResult(res
, 0, false, false, true);
5935 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
5936 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5937 addDS(DNSName("com."), 300, res
->d_records
, keys
);
5938 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
5941 else if (ip
== ComboAddress("192.0.2.1:53")) {
5942 if (domain
== DNSName("com.")) {
5943 setLWResult(res
, 0, true, false, true);
5944 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
5945 addRRSIG(keys
, res
->d_records
, domain
, 300);
5946 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
5947 addRRSIG(keys
, res
->d_records
, domain
, 300);
5950 setLWResult(res
, 0, false, false, true);
5951 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
5953 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
5954 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
5955 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5959 else if (ip
== ComboAddress("192.0.2.2:53")) {
5960 if (type
== QType::NS
) {
5961 if (domain
== DNSName("powerdns.com.")) {
5962 setLWResult(res
, RCode::Refused
, false, false, true);
5965 setLWResult(res
, 0, true, false, true);
5966 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
5967 addRRSIG(keys
, res
->d_records
, domain
, 300);
5968 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
5969 addRRSIG(keys
, res
->d_records
, domain
, 300);
5973 setLWResult(res
, 0, true, false, true);
5974 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
5975 addRRSIG(keys
, res
->d_records
, DNSName("www.powerdns.com"), 300);
5985 vector
<DNSRecord
> ret
;
5986 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5987 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5988 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5989 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5990 BOOST_CHECK_EQUAL(queriesCount
, 9);
5992 /* again, to test the cache */
5994 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
5995 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
5996 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
5997 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
5998 BOOST_CHECK_EQUAL(queriesCount
, 9);
6001 BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_signed_child
) {
6002 /* check that we don't accept a signer below us */
6003 std::unique_ptr
<SyncRes
> sr
;
6006 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6009 const DNSName
target("www.powerdns.com.");
6012 auto luaconfsCopy
= g_luaconfs
.getCopy();
6013 luaconfsCopy
.dsAnchors
.clear();
6014 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6015 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6016 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6017 generateKeyMaterial(DNSName("www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6018 generateKeyMaterial(DNSName("sub.www.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6020 g_luaconfs
.setState(luaconfsCopy
);
6022 size_t queriesCount
= 0;
6024 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
) {
6027 if (type
== QType::DS
) {
6028 DNSName
auth(domain
);
6031 setLWResult(res
, 0, true, false, true);
6032 if (domain
== target
) {
6033 addRecordToLW(res
, domain
, QType::SOA
, "ns1.powerdns.com. blah. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
6034 addRRSIG(keys
, res
->d_records
, target
, 300);
6037 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
6038 addRRSIG(keys
, res
->d_records
, auth
, 300);
6042 else if (type
== QType::DNSKEY
) {
6043 setLWResult(res
, 0, true, false, true);
6044 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6045 if (domain
== DNSName("www.powerdns.com.")) {
6046 addRRSIG(keys
, res
->d_records
, DNSName("sub.www.powerdns.com."), 300);
6049 addRRSIG(keys
, res
->d_records
, domain
, 300);
6054 if (isRootServer(ip
)) {
6055 setLWResult(res
, 0, false, false, true);
6056 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6057 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6058 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6059 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6062 else if (ip
== ComboAddress("192.0.2.1:53")) {
6063 if (domain
== DNSName("com.")) {
6064 setLWResult(res
, 0, true, false, true);
6065 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6066 addRRSIG(keys
, res
->d_records
, domain
, 300);
6067 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6068 addRRSIG(keys
, res
->d_records
, domain
, 300);
6071 setLWResult(res
, 0, false, false, true);
6072 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6073 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6074 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6075 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6079 else if (ip
== ComboAddress("192.0.2.2:53")) {
6080 if (type
== QType::NS
) {
6081 setLWResult(res
, 0, true, false, true);
6082 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6083 addRRSIG(keys
, res
->d_records
, domain
, 300);
6084 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6085 addRRSIG(keys
, res
->d_records
, domain
, 300);
6088 setLWResult(res
, 0, true, false, true);
6089 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
6090 addRRSIG(keys
, res
->d_records
, domain
, 300);
6100 vector
<DNSRecord
> ret
;
6101 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6102 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6103 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6104 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6105 BOOST_CHECK_EQUAL(queriesCount
, 9);
6107 /* again, to test the cache */
6109 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6110 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6111 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6112 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6113 BOOST_CHECK_EQUAL(queriesCount
, 9);
6116 BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure
) {
6117 std::unique_ptr
<SyncRes
> sr
;
6120 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6123 const DNSName
target("www.powerdns.com.");
6126 auto luaconfsCopy
= g_luaconfs
.getCopy();
6127 luaconfsCopy
.dsAnchors
.clear();
6128 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6129 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6131 g_luaconfs
.setState(luaconfsCopy
);
6133 size_t queriesCount
= 0;
6134 size_t dsQueriesCount
= 0;
6136 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
) {
6139 if (type
== QType::DS
) {
6140 DNSName
auth(domain
);
6144 setLWResult(res
, 0, true, false, true);
6145 if (domain
== DNSName("com.")) {
6146 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
6149 addRecordToLW(res
, "com.", QType::SOA
, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6150 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6151 addNSECRecordToLW(domain
, DNSName("powerdnt.com."), { QType::NS
}, 600, res
->d_records
);
6153 addRRSIG(keys
, res
->d_records
, auth
, 300);
6156 else if (type
== QType::DNSKEY
) {
6157 setLWResult(res
, 0, true, false, true);
6158 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6159 addRRSIG(keys
, res
->d_records
, domain
, 300);
6163 if (isRootServer(ip
)) {
6164 setLWResult(res
, 0, false, false, true);
6165 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6166 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6167 /* No DS on referral, and no denial of the DS either */
6170 else if (ip
== ComboAddress("192.0.2.1:53")) {
6171 if (domain
== DNSName("com.")) {
6172 setLWResult(res
, 0, true, false, true);
6173 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6174 addRRSIG(keys
, res
->d_records
, domain
, 300);
6175 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6176 addRRSIG(keys
, res
->d_records
, domain
, 300);
6179 setLWResult(res
, 0, false, false, true);
6180 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6181 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6182 /* No DS on referral, and no denial of the DS either */
6186 else if (ip
== ComboAddress("192.0.2.2:53")) {
6187 setLWResult(res
, 0, true, false, true);
6188 if (type
== QType::NS
) {
6189 if (domain
== DNSName("powerdns.com.")) {
6190 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6191 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6194 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6198 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
6207 vector
<DNSRecord
> ret
;
6208 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6209 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6210 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6211 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6212 BOOST_CHECK_EQUAL(queriesCount
, 7);
6213 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6215 /* again, to test the cache */
6217 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6218 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6219 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6220 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6221 BOOST_CHECK_EQUAL(queriesCount
, 7);
6222 BOOST_CHECK_EQUAL(dsQueriesCount
, 2);
6225 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec
) {
6226 std::unique_ptr
<SyncRes
> sr
;
6229 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6232 const DNSName
target("powerdns.com.");
6235 auto luaconfsCopy
= g_luaconfs
.getCopy();
6236 luaconfsCopy
.dsAnchors
.clear();
6237 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6238 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6239 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6241 g_luaconfs
.setState(luaconfsCopy
);
6243 size_t queriesCount
= 0;
6245 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
) {
6248 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6249 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
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 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6256 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6257 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6260 else if (ip
== ComboAddress("192.0.2.1:53")) {
6261 if (domain
== DNSName("com.")) {
6262 setLWResult(res
, 0, true, false, true);
6263 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6264 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6265 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6268 setLWResult(res
, 0, false, false, true);
6269 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6270 addDS(domain
, 300, res
->d_records
, keys
);
6271 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6272 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6276 else if (ip
== ComboAddress("192.0.2.2:53")) {
6277 setLWResult(res
, 0, true, false, true);
6278 if (type
== QType::NS
) {
6279 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6280 addRRSIG(keys
, res
->d_records
, domain
, 300);
6283 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6284 addRRSIG(keys
, res
->d_records
, domain
, 300);
6285 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
, QType::DNSKEY
}, 600, res
->d_records
);
6286 /* NO RRSIG for the NSEC record! */
6295 /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
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(), Bogus
);
6300 BOOST_CHECK_EQUAL(ret
.size(), 3);
6301 BOOST_CHECK_EQUAL(queriesCount
, 8);
6303 /* again, to test the cache */
6305 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6306 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6307 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6308 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
6309 BOOST_CHECK_EQUAL(queriesCount
, 8);
6312 BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec
) {
6313 std::unique_ptr
<SyncRes
> sr
;
6316 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6319 const DNSName
target("powerdns.com.");
6322 auto luaconfsCopy
= g_luaconfs
.getCopy();
6323 luaconfsCopy
.dsAnchors
.clear();
6324 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6325 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6326 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6328 g_luaconfs
.setState(luaconfsCopy
);
6330 size_t queriesCount
= 0;
6332 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
) {
6335 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6336 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6339 if (isRootServer(ip
)) {
6340 setLWResult(res
, 0, false, false, true);
6341 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6342 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6343 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6344 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6347 else if (ip
== ComboAddress("192.0.2.1:53")) {
6348 if (domain
== DNSName("com.")) {
6349 setLWResult(res
, 0, true, false, true);
6350 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6351 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6352 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6355 setLWResult(res
, 0, false, false, true);
6356 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6357 addDS(domain
, 300, res
->d_records
, keys
);
6358 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6359 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6363 else if (ip
== ComboAddress("192.0.2.2:53")) {
6364 setLWResult(res
, 0, true, false, true);
6365 if (type
== QType::NS
) {
6366 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6367 addRRSIG(keys
, res
->d_records
, domain
, 300);
6370 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6371 addRRSIG(keys
, res
->d_records
, domain
, 300);
6373 /* NO NSEC record! */
6382 /* no NSEC record in a secure zone, should be Bogus! */
6383 vector
<DNSRecord
> ret
;
6384 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6385 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6386 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6387 BOOST_CHECK_EQUAL(ret
.size(), 2);
6388 BOOST_CHECK_EQUAL(queriesCount
, 8);
6390 /* again, to test the cache */
6392 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6393 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6394 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
6395 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6396 BOOST_CHECK_EQUAL(queriesCount
, 8);
6399 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure
) {
6400 std::unique_ptr
<SyncRes
> sr
;
6403 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6406 const DNSName
target("powerdns.com.");
6407 const ComboAddress
targetAddr("192.0.2.42");
6410 auto luaconfsCopy
= g_luaconfs
.getCopy();
6411 luaconfsCopy
.dsAnchors
.clear();
6412 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6413 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6415 g_luaconfs
.setState(luaconfsCopy
);
6417 size_t queriesCount
= 0;
6419 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
) {
6422 if (type
== QType::DS
) {
6423 if (domain
== target
) {
6424 setLWResult(res
, 0, false, false, true);
6425 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6426 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6427 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6430 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6433 else if (type
== QType::DNSKEY
) {
6434 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6435 setLWResult(res
, 0, true, false, true);
6436 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6437 addRRSIG(keys
, res
->d_records
, domain
, 300);
6441 setLWResult(res
, 0, false, false, true);
6442 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6447 if (isRootServer(ip
)) {
6448 setLWResult(res
, 0, false, false, true);
6449 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6450 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6451 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6452 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6455 else if (ip
== ComboAddress("192.0.2.1:53")) {
6456 if (domain
== DNSName("com.")) {
6457 setLWResult(res
, 0, true, false, true);
6458 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6459 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6460 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6463 setLWResult(res
, 0, false, false, true);
6464 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6466 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6467 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6468 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6472 else if (ip
== ComboAddress("192.0.2.2:53")) {
6473 setLWResult(res
, 0, true, false, true);
6474 if (type
== QType::NS
) {
6475 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6478 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString());
6487 vector
<DNSRecord
> ret
;
6488 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6489 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6490 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6491 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6492 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6493 /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
6494 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
6496 BOOST_CHECK_EQUAL(queriesCount
, 7);
6498 /* again, to test the cache */
6500 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6501 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6502 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6503 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6504 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6505 BOOST_CHECK_EQUAL(queriesCount
, 7);
6509 BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_ds
) {
6512 - parent is secure, zone is secure: DS should be secure
6514 std::unique_ptr
<SyncRes
> sr
;
6517 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6520 const DNSName
target("powerdns.com.");
6523 auto luaconfsCopy
= g_luaconfs
.getCopy();
6524 luaconfsCopy
.dsAnchors
.clear();
6525 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6526 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6527 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6529 g_luaconfs
.setState(luaconfsCopy
);
6531 size_t queriesCount
= 0;
6533 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
) {
6536 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6537 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6540 if (isRootServer(ip
)) {
6541 setLWResult(res
, 0, false, false, true);
6542 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6543 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6544 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6545 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6553 vector
<DNSRecord
> ret
;
6554 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6555 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6556 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6557 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6558 for (const auto& record
: ret
) {
6559 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6561 BOOST_CHECK_EQUAL(queriesCount
, 4);
6563 /* again, to test the cache */
6565 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6566 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6567 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6568 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6569 for (const auto& record
: ret
) {
6570 BOOST_CHECK(record
.d_type
== QType::DS
|| record
.d_type
== QType::RRSIG
);
6572 BOOST_CHECK_EQUAL(queriesCount
, 4);
6575 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_ds
) {
6578 - parent is secure, zone is insecure: DS denial should be secure
6580 std::unique_ptr
<SyncRes
> sr
;
6583 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6586 const DNSName
target("powerdns.com.");
6589 auto luaconfsCopy
= g_luaconfs
.getCopy();
6590 luaconfsCopy
.dsAnchors
.clear();
6591 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6592 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6594 g_luaconfs
.setState(luaconfsCopy
);
6596 size_t queriesCount
= 0;
6598 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
) {
6601 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
6602 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6605 if (isRootServer(ip
)) {
6606 setLWResult(res
, 0, false, false, true);
6607 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6608 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6609 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6610 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6618 vector
<DNSRecord
> ret
;
6619 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6620 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6621 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6622 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6623 for (const auto& record
: ret
) {
6624 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6626 BOOST_CHECK_EQUAL(queriesCount
, 4);
6628 /* again, to test the cache */
6630 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
6631 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6632 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6633 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
6634 for (const auto& record
: ret
) {
6635 BOOST_CHECK(record
.d_type
== QType::SOA
|| record
.d_type
== QType::NSEC
|| record
.d_type
== QType::RRSIG
);
6637 BOOST_CHECK_EQUAL(queriesCount
, 4);
6640 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut
) {
6641 std::unique_ptr
<SyncRes
> sr
;
6644 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6647 const DNSName
target("www.sub.powerdns.com.");
6648 const ComboAddress
targetAddr("192.0.2.42");
6651 auto luaconfsCopy
= g_luaconfs
.getCopy();
6652 luaconfsCopy
.dsAnchors
.clear();
6653 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6654 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6655 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6657 g_luaconfs
.setState(luaconfsCopy
);
6659 size_t queriesCount
= 0;
6661 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
) {
6664 if (type
== QType::DS
) {
6665 if (domain
== DNSName("sub.powerdns.com.")) {
6666 setLWResult(res
, 0, false, false, true);
6667 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6668 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6669 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6670 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6673 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6674 setLWResult(res
, 0, false, false, true);
6675 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);
6679 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6682 else if (type
== QType::DNSKEY
) {
6683 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
6684 setLWResult(res
, 0, true, false, true);
6685 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6686 addRRSIG(keys
, res
->d_records
, domain
, 300);
6690 setLWResult(res
, 0, false, false, true);
6691 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6696 if (isRootServer(ip
)) {
6697 setLWResult(res
, 0, false, false, true);
6698 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6699 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6700 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6701 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6704 else if (ip
== ComboAddress("192.0.2.1:53")) {
6705 if (domain
== DNSName("com.")) {
6706 setLWResult(res
, 0, true, false, true);
6707 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6708 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6709 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6712 setLWResult(res
, 0, false, false, true);
6713 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6714 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
6715 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6716 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6720 else if (ip
== ComboAddress("192.0.2.2:53")) {
6721 setLWResult(res
, 0, true, false, true);
6722 if (type
== QType::NS
) {
6723 if (domain
== DNSName("www.sub.powerdns.com.")) {
6724 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);
6726 else if (domain
== DNSName("sub.powerdns.com.")) {
6727 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6729 else if (domain
== DNSName("powerdns.com.")) {
6730 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6731 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com."), 300);
6734 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6743 vector
<DNSRecord
> ret
;
6744 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6745 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6746 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6747 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6748 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6749 BOOST_CHECK_EQUAL(queriesCount
, 9);
6751 /* again, to test the cache */
6753 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6754 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6755 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6756 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6757 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6758 BOOST_CHECK_EQUAL(queriesCount
, 9);
6761 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut
) {
6762 std::unique_ptr
<SyncRes
> sr
;
6765 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6768 const DNSName
target("www.sub.powerdns.com.");
6769 const ComboAddress
targetAddr("192.0.2.42");
6772 auto luaconfsCopy
= g_luaconfs
.getCopy();
6773 luaconfsCopy
.dsAnchors
.clear();
6774 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6775 /* No key material for .com */
6776 /* But TA for sub.powerdns.com. */
6777 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6778 luaconfsCopy
.dsAnchors
[DNSName("sub.powerdns.com.")].insert(keys
[DNSName("sub.powerdns.com.")].second
);
6779 g_luaconfs
.setState(luaconfsCopy
);
6781 size_t queriesCount
= 0;
6783 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
) {
6786 if (type
== QType::DS
) {
6787 if (domain
== DNSName("www.sub.powerdns.com")) {
6788 setLWResult(res
, 0, false, false, true);
6789 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);
6790 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6791 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6792 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6795 setLWResult(res
, 0, false, false, true);
6797 if (domain
== DNSName("com.")) {
6798 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6800 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6801 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6804 setLWResult(res
, 0, false, false, true);
6805 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6810 else if (type
== QType::DNSKEY
) {
6811 if (domain
== g_rootdnsname
|| domain
== DNSName("sub.powerdns.com.")) {
6812 setLWResult(res
, 0, true, false, true);
6813 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6814 addRRSIG(keys
, res
->d_records
, domain
, 300);
6819 if (isRootServer(ip
)) {
6820 setLWResult(res
, 0, false, false, true);
6821 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6823 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS
}, 600, res
->d_records
);
6824 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6825 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6828 else if (ip
== ComboAddress("192.0.2.1:53")) {
6829 if (domain
== DNSName("com.")) {
6830 setLWResult(res
, 0, true, false, true);
6831 addRecordToLW(res
, DNSName("com."), QType::NS
, "a.gtld-servers.com.");
6832 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6834 else if (domain
.isPartOf(DNSName("powerdns.com."))) {
6835 setLWResult(res
, 0, false, false, true);
6836 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6837 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6841 else if (ip
== ComboAddress("192.0.2.2:53")) {
6842 setLWResult(res
, 0, true, false, true);
6843 if (type
== QType::NS
) {
6844 if (domain
== DNSName("www.sub.powerdns.com.")) {
6845 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);
6846 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6847 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A
}, 600, res
->d_records
);
6848 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com"), 300);
6850 else if (domain
== DNSName("sub.powerdns.com.")) {
6851 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6852 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6854 else if (domain
== DNSName("powerdns.com.")) {
6855 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6858 else if (domain
== DNSName("www.sub.powerdns.com.")) {
6859 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
6860 addRRSIG(keys
, res
->d_records
, DNSName("sub.powerdns.com."), 300);
6869 vector
<DNSRecord
> ret
;
6870 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6871 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6872 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6873 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6874 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6875 BOOST_CHECK_EQUAL(queriesCount
, 7);
6877 /* again, to test the cache */
6879 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6880 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6881 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
6882 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
6883 BOOST_CHECK(ret
[0].d_type
== QType::A
);
6884 BOOST_CHECK_EQUAL(queriesCount
, 7);
6887 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata
) {
6888 std::unique_ptr
<SyncRes
> sr
;
6891 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
6894 const DNSName
target("powerdns.com.");
6897 auto luaconfsCopy
= g_luaconfs
.getCopy();
6898 luaconfsCopy
.dsAnchors
.clear();
6899 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
6900 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
6902 g_luaconfs
.setState(luaconfsCopy
);
6904 size_t queriesCount
= 0;
6906 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
) {
6909 if (type
== QType::DS
) {
6910 if (domain
== target
) {
6911 setLWResult(res
, 0, false, false, true);
6912 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6913 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6914 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6918 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
6921 else if (type
== QType::DNSKEY
) {
6922 if (domain
== g_rootdnsname
|| domain
== DNSName("com.")) {
6923 setLWResult(res
, 0, true, false, true);
6924 addDNSKEY(keys
, domain
, 300, res
->d_records
);
6925 addRRSIG(keys
, res
->d_records
, domain
, 300);
6929 setLWResult(res
, 0, false, false, true);
6930 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6935 if (isRootServer(ip
)) {
6936 setLWResult(res
, 0, false, false, true);
6937 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
6938 addDS(DNSName("com."), 300, res
->d_records
, keys
);
6939 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
6940 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6943 else if (ip
== ComboAddress("192.0.2.1:53")) {
6944 if (domain
== DNSName("com.")) {
6945 setLWResult(res
, 0, true, false, true);
6946 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
6947 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6948 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
6949 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6952 setLWResult(res
, 0, false, false, true);
6953 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
6955 addNSECRecordToLW(domain
, DNSName("z.powerdns.com."), { QType::NS
}, 600, res
->d_records
);
6956 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
6957 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6961 else if (ip
== ComboAddress("192.0.2.2:53")) {
6962 if (type
== QType::NS
) {
6963 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
6964 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
6967 setLWResult(res
, 0, true, false, true);
6968 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
6977 vector
<DNSRecord
> ret
;
6978 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6979 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6980 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6981 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6982 /* 4 NS (com from root, com from com, powerdns.com from com,
6983 powerdns.com from powerdns.com)
6984 2 DNSKEY (. and com., none for powerdns.com because no DS)
6987 BOOST_CHECK_EQUAL(queriesCount
, 7);
6989 /* again, to test the cache */
6991 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
6992 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
6993 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
6994 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
6995 BOOST_CHECK_EQUAL(queriesCount
, 7);
6998 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname
) {
6999 std::unique_ptr
<SyncRes
> sr
;
7002 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7005 const DNSName
target("powerdns.com.");
7006 const DNSName
targetCName("power-dns.com.");
7007 const ComboAddress
targetCNameAddr("192.0.2.42");
7010 auto luaconfsCopy
= g_luaconfs
.getCopy();
7011 luaconfsCopy
.dsAnchors
.clear();
7012 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7013 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7014 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7015 g_luaconfs
.setState(luaconfsCopy
);
7017 size_t queriesCount
= 0;
7019 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
) {
7022 if (type
== QType::DS
) {
7023 if (domain
== targetCName
) {
7024 setLWResult(res
, 0, false, false, true);
7025 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7026 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7027 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7031 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7034 else if (type
== QType::DNSKEY
) {
7035 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7036 setLWResult(res
, 0, true, false, true);
7037 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7038 addRRSIG(keys
, res
->d_records
, domain
, 300);
7042 setLWResult(res
, 0, false, false, true);
7043 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7048 if (isRootServer(ip
)) {
7049 setLWResult(res
, 0, false, false, true);
7050 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7051 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7052 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7053 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7056 else if (ip
== ComboAddress("192.0.2.1:53")) {
7057 setLWResult(res
, 0, false, false, true);
7058 if (domain
== DNSName("com.")) {
7059 setLWResult(res
, 0, true, false, true);
7060 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7061 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7062 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7063 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7066 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7067 if (domain
== DNSName("powerdns.com.")) {
7068 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7070 else if (domain
== targetCName
) {
7071 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7073 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7074 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7079 else if (ip
== ComboAddress("192.0.2.2:53")) {
7080 setLWResult(res
, 0, true, false, true);
7082 if (type
== QType::NS
) {
7083 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7084 if (domain
== DNSName("powerdns.com.")) {
7085 addRRSIG(keys
, res
->d_records
, domain
, 300);
7087 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7088 if (domain
== DNSName("powerdns.com.")) {
7089 addRRSIG(keys
, res
->d_records
, domain
, 300);
7093 if (domain
== DNSName("powerdns.com.")) {
7094 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7095 addRRSIG(keys
, res
->d_records
, domain
, 300);
7097 else if (domain
== targetCName
) {
7098 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7109 vector
<DNSRecord
> ret
;
7110 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7111 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7112 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7113 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7114 BOOST_CHECK_EQUAL(queriesCount
, 11);
7116 /* again, to test the cache */
7118 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7119 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7120 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7121 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7122 BOOST_CHECK_EQUAL(queriesCount
, 11);
7125 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname_glue
) {
7126 std::unique_ptr
<SyncRes
> sr
;
7129 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7132 const DNSName
target("powerdns.com.");
7133 const DNSName
targetCName1("cname.sub.powerdns.com.");
7134 const DNSName
targetCName2("cname2.sub.powerdns.com.");
7135 const ComboAddress
targetCName2Addr("192.0.2.42");
7138 auto luaconfsCopy
= g_luaconfs
.getCopy();
7139 luaconfsCopy
.dsAnchors
.clear();
7140 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7141 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7142 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7143 g_luaconfs
.setState(luaconfsCopy
);
7145 size_t queriesCount
= 0;
7147 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
) {
7150 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7151 if (domain
== DNSName("sub.powerdns.com")) {
7152 setLWResult(res
, 0, false, false, true);
7153 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7154 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7155 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7159 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7163 if (isRootServer(ip
)) {
7164 setLWResult(res
, 0, false, false, true);
7165 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7166 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7167 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7168 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7171 else if (ip
== ComboAddress("192.0.2.1:53")) {
7172 setLWResult(res
, 0, false, false, true);
7173 if (domain
== DNSName("com.")) {
7174 setLWResult(res
, 0, true, false, true);
7175 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7176 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7177 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7178 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7181 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7182 if (domain
== DNSName("powerdns.com.")) {
7183 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7185 else if (domain
== DNSName("sub.powerdns.com")) {
7186 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7188 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7189 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7194 else if (ip
== ComboAddress("192.0.2.2:53")) {
7195 setLWResult(res
, 0, true, false, true);
7197 if (type
== QType::NS
) {
7198 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7199 if (domain
== DNSName("powerdns.com.")) {
7200 addRRSIG(keys
, res
->d_records
, domain
, 300);
7202 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7203 if (domain
== DNSName("powerdns.com.")) {
7204 addRRSIG(keys
, res
->d_records
, domain
, 300);
7208 if (domain
== DNSName("powerdns.com.")) {
7209 addRecordToLW(res
, domain
, QType::CNAME
, targetCName1
.toString());
7210 addRRSIG(keys
, res
->d_records
, domain
, 300);
7211 /* add the CNAME target as a glue, with no RRSIG since the sub zone is insecure */
7212 addRecordToLW(res
, targetCName1
, QType::CNAME
, targetCName2
.toString());
7213 addRecordToLW(res
, targetCName2
, QType::A
, targetCName2Addr
.toString());
7215 else if (domain
== targetCName1
) {
7216 addRecordToLW(res
, domain
, QType::CNAME
, targetCName2
.toString());
7218 else if (domain
== targetCName2
) {
7219 addRecordToLW(res
, domain
, QType::A
, targetCName2Addr
.toString());
7230 vector
<DNSRecord
> ret
;
7231 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7232 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7233 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7234 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7235 BOOST_CHECK_EQUAL(queriesCount
, 11);
7237 /* again, to test the cache */
7239 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7240 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7241 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7242 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7243 BOOST_CHECK_EQUAL(queriesCount
, 11);
7246 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname
) {
7247 std::unique_ptr
<SyncRes
> sr
;
7250 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7253 const DNSName
target("power-dns.com.");
7254 const DNSName
targetCName("powerdns.com.");
7255 const ComboAddress
targetCNameAddr("192.0.2.42");
7258 auto luaconfsCopy
= g_luaconfs
.getCopy();
7259 luaconfsCopy
.dsAnchors
.clear();
7260 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7261 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7262 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7263 g_luaconfs
.setState(luaconfsCopy
);
7265 size_t queriesCount
= 0;
7267 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
) {
7270 if (type
== QType::DS
) {
7271 if (domain
== DNSName("power-dns.com.")) {
7272 setLWResult(res
, 0, false, false, true);
7273 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7274 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7275 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7279 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7282 else if (type
== QType::DNSKEY
) {
7283 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7284 setLWResult(res
, 0, true, false, true);
7285 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7286 addRRSIG(keys
, res
->d_records
, domain
, 300);
7290 setLWResult(res
, 0, false, false, true);
7291 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7296 if (isRootServer(ip
)) {
7297 setLWResult(res
, 0, false, false, true);
7298 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7299 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7300 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7301 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7304 else if (ip
== ComboAddress("192.0.2.1:53")) {
7305 if (domain
== DNSName("com.")) {
7306 setLWResult(res
, 0, true, false, true);
7307 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7308 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7309 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7310 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7312 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7313 setLWResult(res
, 0, false, false, true);
7314 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7315 if (domain
== targetCName
) {
7316 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7318 else if (domain
== target
) {
7319 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7321 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7322 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7326 else if (ip
== ComboAddress("192.0.2.2:53")) {
7327 setLWResult(res
, 0, true, false, true);
7328 if (type
== QType::NS
) {
7329 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7330 if (domain
== DNSName("powerdns.com.")) {
7331 addRRSIG(keys
, res
->d_records
, domain
, 300);
7333 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7334 if (domain
== DNSName("powerdns.com.")) {
7335 addRRSIG(keys
, res
->d_records
, domain
, 300);
7339 if (domain
== target
) {
7340 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7342 else if (domain
== targetCName
) {
7343 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7344 addRRSIG(keys
, res
->d_records
, domain
, 300);
7354 vector
<DNSRecord
> ret
;
7355 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7356 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7357 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7358 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7359 BOOST_CHECK_EQUAL(queriesCount
, 11);
7361 /* again, to test the cache */
7363 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7364 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7365 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
7366 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7367 BOOST_CHECK_EQUAL(queriesCount
, 11);
7370 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname
) {
7371 std::unique_ptr
<SyncRes
> sr
;
7374 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7377 const DNSName
target("power-dns.com.");
7378 const DNSName
targetCName("powerdns.com.");
7379 const ComboAddress
targetCNameAddr("192.0.2.42");
7382 auto luaconfsCopy
= g_luaconfs
.getCopy();
7383 luaconfsCopy
.dsAnchors
.clear();
7384 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7385 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7386 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7387 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7388 g_luaconfs
.setState(luaconfsCopy
);
7390 size_t queriesCount
= 0;
7392 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
) {
7395 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7396 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7399 if (isRootServer(ip
)) {
7400 setLWResult(res
, 0, false, false, true);
7401 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7402 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7403 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7404 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7407 else if (ip
== ComboAddress("192.0.2.1:53")) {
7408 if (domain
== DNSName("com.")) {
7409 setLWResult(res
, 0, true, false, true);
7410 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7411 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7412 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7413 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7415 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7416 setLWResult(res
, 0, false, false, true);
7417 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7418 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7419 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7420 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7424 else if (ip
== ComboAddress("192.0.2.2:53")) {
7425 setLWResult(res
, 0, true, false, true);
7426 if (type
== QType::NS
) {
7427 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7428 addRRSIG(keys
, res
->d_records
, domain
, 300);
7429 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7430 addRRSIG(keys
, res
->d_records
, domain
, 300);
7433 if (domain
== target
) {
7434 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7435 /* No RRSIG, leading to bogus */
7437 else if (domain
== targetCName
) {
7438 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7439 addRRSIG(keys
, res
->d_records
, domain
, 300);
7449 vector
<DNSRecord
> ret
;
7450 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7451 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7452 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7453 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7454 BOOST_CHECK_EQUAL(queriesCount
, 11);
7456 /* again, to test the cache */
7458 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7459 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7460 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7461 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7462 BOOST_CHECK_EQUAL(queriesCount
, 11);
7465 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname
) {
7466 std::unique_ptr
<SyncRes
> sr
;
7469 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7472 const DNSName
target("power-dns.com.");
7473 const DNSName
targetCName("powerdns.com.");
7474 const ComboAddress
targetCNameAddr("192.0.2.42");
7477 auto luaconfsCopy
= g_luaconfs
.getCopy();
7478 luaconfsCopy
.dsAnchors
.clear();
7479 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7480 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7481 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7482 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7483 g_luaconfs
.setState(luaconfsCopy
);
7485 size_t queriesCount
= 0;
7487 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
) {
7490 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7491 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7494 if (isRootServer(ip
)) {
7495 setLWResult(res
, 0, false, false, true);
7496 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7497 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7498 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7499 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7502 else if (ip
== ComboAddress("192.0.2.1:53")) {
7503 if (domain
== DNSName("com.")) {
7504 setLWResult(res
, 0, true, false, true);
7505 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7506 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7507 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7508 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7510 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7511 setLWResult(res
, 0, false, false, true);
7512 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7513 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7514 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7515 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7519 else if (ip
== ComboAddress("192.0.2.2:53")) {
7520 setLWResult(res
, 0, true, false, true);
7521 if (type
== QType::NS
) {
7522 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7523 addRRSIG(keys
, res
->d_records
, domain
, 300);
7524 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7525 addRRSIG(keys
, res
->d_records
, domain
, 300);
7528 if (domain
== target
) {
7529 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7530 addRRSIG(keys
, res
->d_records
, domain
, 300);
7532 else if (domain
== targetCName
) {
7533 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7534 /* No RRSIG, leading to bogus */
7544 vector
<DNSRecord
> ret
;
7545 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7546 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7547 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7548 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7549 BOOST_CHECK_EQUAL(queriesCount
, 11);
7551 /* again, to test the cache */
7553 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7554 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7555 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7556 BOOST_REQUIRE_EQUAL(ret
.size(), 3);
7557 BOOST_CHECK_EQUAL(queriesCount
, 11);
7560 BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname
) {
7561 std::unique_ptr
<SyncRes
> sr
;
7564 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7567 const DNSName
target("power-dns.com.");
7568 const DNSName
targetCName("powerdns.com.");
7569 const ComboAddress
targetCNameAddr("192.0.2.42");
7572 auto luaconfsCopy
= g_luaconfs
.getCopy();
7573 luaconfsCopy
.dsAnchors
.clear();
7574 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7575 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7576 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7577 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7578 g_luaconfs
.setState(luaconfsCopy
);
7580 size_t queriesCount
= 0;
7582 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
) {
7585 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
7586 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7589 if (isRootServer(ip
)) {
7590 setLWResult(res
, 0, false, false, true);
7591 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7592 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7593 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7594 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7597 else if (ip
== ComboAddress("192.0.2.1:53")) {
7598 if (domain
== DNSName("com.")) {
7599 setLWResult(res
, 0, true, false, true);
7600 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7601 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7602 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7603 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7605 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7606 setLWResult(res
, 0, false, false, true);
7607 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7608 addDS(DNSName(domain
), 300, res
->d_records
, keys
);
7609 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7610 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7614 else if (ip
== ComboAddress("192.0.2.2:53")) {
7615 setLWResult(res
, 0, true, false, true);
7616 if (type
== QType::NS
) {
7617 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7618 addRRSIG(keys
, res
->d_records
, domain
, 300);
7619 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7620 addRRSIG(keys
, res
->d_records
, domain
, 300);
7623 if (domain
== target
) {
7624 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7625 addRRSIG(keys
, res
->d_records
, domain
, 300);
7627 else if (domain
== targetCName
) {
7628 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7629 addRRSIG(keys
, res
->d_records
, domain
, 300);
7639 vector
<DNSRecord
> ret
;
7640 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7641 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7642 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7643 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7644 BOOST_CHECK_EQUAL(queriesCount
, 12);
7646 /* again, to test the cache */
7648 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7649 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7650 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7651 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
7652 BOOST_CHECK_EQUAL(queriesCount
, 12);
7655 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname
) {
7656 std::unique_ptr
<SyncRes
> sr
;
7659 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7662 const DNSName
target("powerdns.com.");
7663 const DNSName
targetCName("power-dns.com.");
7664 const ComboAddress
targetCNameAddr("192.0.2.42");
7667 auto luaconfsCopy
= g_luaconfs
.getCopy();
7668 luaconfsCopy
.dsAnchors
.clear();
7669 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7670 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7671 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7672 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7673 g_luaconfs
.setState(luaconfsCopy
);
7675 size_t queriesCount
= 0;
7677 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
) {
7680 if (type
== QType::DS
) {
7681 if (domain
== DNSName("power-dns.com.")) {
7682 setLWResult(res
, 0, false, false, true);
7683 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7684 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7685 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7689 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
7692 else if (type
== QType::DNSKEY
) {
7693 if (domain
== g_rootdnsname
|| domain
== DNSName("com.") || domain
== DNSName("powerdns.com.")) {
7694 setLWResult(res
, 0, true, false, true);
7695 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7696 addRRSIG(keys
, res
->d_records
, domain
, 300);
7700 setLWResult(res
, 0, false, false, true);
7701 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7706 if (isRootServer(ip
)) {
7707 setLWResult(res
, 0, false, false, true);
7708 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7709 addDS(DNSName("com."), 300, res
->d_records
, keys
);
7710 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7711 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7714 else if (ip
== ComboAddress("192.0.2.1:53")) {
7715 if (domain
== DNSName("com.")) {
7716 setLWResult(res
, 0, true, false, true);
7717 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7718 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7719 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7720 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7722 else if (domain
== DNSName("powerdns.com.") || domain
== DNSName("power-dns.com.")) {
7723 setLWResult(res
, 0, false, false, true);
7724 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7725 if (domain
== DNSName("powerdns.com.")) {
7726 addDS(DNSName("powerdns.com."), 300, res
->d_records
, keys
);
7728 else if (domain
== targetCName
) {
7729 addNSECRecordToLW(domain
, DNSName("z.power-dns.com."), { QType::NS
}, 600, res
->d_records
);
7731 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
7732 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7736 else if (ip
== ComboAddress("192.0.2.2:53")) {
7737 setLWResult(res
, 0, true, false, true);
7738 if (type
== QType::NS
) {
7739 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7740 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7743 if (domain
== DNSName("powerdns.com.")) {
7744 addRecordToLW(res
, domain
, QType::CNAME
, targetCName
.toString());
7745 /* No RRSIG -> Bogus */
7747 else if (domain
== targetCName
) {
7748 addRecordToLW(res
, domain
, QType::A
, targetCNameAddr
.toString());
7758 vector
<DNSRecord
> ret
;
7759 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7760 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7761 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7762 /* no RRSIG to show */
7763 BOOST_CHECK_EQUAL(ret
.size(), 2);
7764 BOOST_CHECK_EQUAL(queriesCount
, 10);
7766 /* again, to test the cache */
7768 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7769 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7770 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7771 BOOST_CHECK_EQUAL(ret
.size(), 2);
7772 BOOST_CHECK_EQUAL(queriesCount
, 10);
7775 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta
) {
7776 std::unique_ptr
<SyncRes
> sr
;
7779 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7782 const DNSName
target("powerdns.com.");
7783 const ComboAddress
targetAddr("192.0.2.42");
7786 auto luaconfsCopy
= g_luaconfs
.getCopy();
7787 luaconfsCopy
.dsAnchors
.clear();
7788 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7789 /* No key material for .com */
7790 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7791 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7792 g_luaconfs
.setState(luaconfsCopy
);
7794 size_t queriesCount
= 0;
7796 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
) {
7799 if (type
== QType::DNSKEY
) {
7800 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7801 setLWResult(res
, 0, true, false, true);
7802 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7803 addRRSIG(keys
, res
->d_records
, domain
, 300);
7806 else if (domain
== DNSName("com.")) {
7807 setLWResult(res
, 0, false, false, true);
7808 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7813 if (isRootServer(ip
)) {
7814 setLWResult(res
, 0, false, false, true);
7815 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7816 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7817 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7818 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7821 else if (ip
== ComboAddress("192.0.2.1:53")) {
7822 if (target
== domain
) {
7823 setLWResult(res
, 0, false, false, true);
7824 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7825 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7827 else if (domain
== DNSName("com.")) {
7828 setLWResult(res
, 0, true, false, true);
7829 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7830 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7834 else if (ip
== ComboAddress("192.0.2.2:53")) {
7835 setLWResult(res
, 0, true, false, true);
7836 if (type
== QType::NS
) {
7837 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7840 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7842 addRRSIG(keys
, res
->d_records
, domain
, 300);
7850 vector
<DNSRecord
> ret
;
7851 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7852 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7853 /* should be insecure but we have a TA for powerdns.com. */
7854 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7855 /* We got a RRSIG */
7856 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7857 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7858 BOOST_CHECK_EQUAL(queriesCount
, 5);
7860 /* again, to test the cache */
7862 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7863 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7864 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
7865 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
7866 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7867 BOOST_CHECK_EQUAL(queriesCount
, 5);
7870 BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig
) {
7871 std::unique_ptr
<SyncRes
> sr
;
7874 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7877 const DNSName
target("powerdns.com.");
7878 const ComboAddress
targetAddr("192.0.2.42");
7881 auto luaconfsCopy
= g_luaconfs
.getCopy();
7882 luaconfsCopy
.dsAnchors
.clear();
7883 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7884 /* No key material for .com */
7885 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
7886 luaconfsCopy
.dsAnchors
[target
].insert(keys
[target
].second
);
7887 g_luaconfs
.setState(luaconfsCopy
);
7889 size_t queriesCount
= 0;
7891 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
) {
7894 if (type
== QType::DNSKEY
) {
7895 if (domain
== g_rootdnsname
|| domain
== DNSName("powerdns.com.")) {
7896 setLWResult(res
, 0, true, false, true);
7897 addDNSKEY(keys
, domain
, 300, res
->d_records
);
7898 addRRSIG(keys
, res
->d_records
, domain
, 300);
7901 else if (domain
== DNSName("com.")) {
7902 setLWResult(res
, 0, false, false, true);
7903 addRecordToLW(res
, domain
, QType::SOA
, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
7908 if (target
.isPartOf(domain
) && isRootServer(ip
)) {
7909 setLWResult(res
, 0, false, false, true);
7910 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
7911 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS
}, 600, res
->d_records
);
7912 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
7913 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7916 else if (ip
== ComboAddress("192.0.2.1:53")) {
7917 if (target
== domain
) {
7918 setLWResult(res
, 0, false, false, true);
7919 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
7920 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
7922 else if (domain
== DNSName("com.")) {
7923 setLWResult(res
, 0, true, false, true);
7924 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
7925 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
7929 else if (domain
== target
&& ip
== ComboAddress("192.0.2.2:53")) {
7930 setLWResult(res
, 0, true, false, true);
7931 if (type
== QType::NS
) {
7932 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
7935 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
7937 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
7945 vector
<DNSRecord
> ret
;
7946 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7947 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7948 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
7949 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7951 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7952 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7953 BOOST_CHECK_EQUAL(queriesCount
, 4);
7955 /* again, to test the cache */
7957 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
7958 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
7959 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
7960 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
7961 BOOST_CHECK(ret
[0].d_type
== QType::A
);
7962 BOOST_CHECK_EQUAL(queriesCount
, 4);
7965 BOOST_AUTO_TEST_CASE(test_dnssec_nta
) {
7966 std::unique_ptr
<SyncRes
> sr
;
7969 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
7972 const DNSName
target(".");
7975 auto luaconfsCopy
= g_luaconfs
.getCopy();
7976 luaconfsCopy
.dsAnchors
.clear();
7977 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
7978 /* Add a NTA for "." */
7979 luaconfsCopy
.negAnchors
[g_rootdnsname
] = "NTA for Root";
7980 g_luaconfs
.setState(luaconfsCopy
);
7982 size_t queriesCount
= 0;
7984 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
) {
7987 if (domain
== target
&& type
== QType::NS
) {
7989 setLWResult(res
, 0, true, false, true);
7990 char addr
[] = "a.root-servers.net.";
7991 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
7993 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
7996 addRRSIG(keys
, res
->d_records
, domain
, 300);
7998 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
7999 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
8002 } else if (domain
== target
&& type
== QType::DNSKEY
) {
8004 setLWResult(res
, 0, true, false, true);
8014 vector
<DNSRecord
> ret
;
8015 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8016 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8017 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8018 /* 13 NS + 1 RRSIG */
8019 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
8020 BOOST_CHECK_EQUAL(queriesCount
, 1);
8022 /* again, to test the cache */
8024 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8025 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8026 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8027 BOOST_REQUIRE_EQUAL(ret
.size(), 14);
8028 BOOST_CHECK_EQUAL(queriesCount
, 1);
8031 BOOST_AUTO_TEST_CASE(test_dnssec_no_ta
) {
8032 std::unique_ptr
<SyncRes
> sr
;
8035 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8038 const DNSName
target(".");
8041 /* Remove the root DS */
8042 auto luaconfsCopy
= g_luaconfs
.getCopy();
8043 luaconfsCopy
.dsAnchors
.clear();
8044 g_luaconfs
.setState(luaconfsCopy
);
8046 size_t queriesCount
= 0;
8048 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
) {
8051 if (domain
== target
&& type
== QType::NS
) {
8053 setLWResult(res
, 0, true, false, true);
8054 char addr
[] = "a.root-servers.net.";
8055 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
8057 addRecordToLW(res
, domain
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
8060 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
8061 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
8069 vector
<DNSRecord
> ret
;
8070 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8071 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8072 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8073 /* 13 NS + 0 RRSIG */
8074 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
8075 BOOST_CHECK_EQUAL(queriesCount
, 1);
8077 /* again, to test the cache */
8079 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
8080 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8081 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
8082 BOOST_REQUIRE_EQUAL(ret
.size(), 13);
8083 BOOST_CHECK_EQUAL(queriesCount
, 1);
8086 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata
) {
8087 std::unique_ptr
<SyncRes
> sr
;
8090 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8093 const DNSName
target("powerdns.com.");
8096 auto luaconfsCopy
= g_luaconfs
.getCopy();
8097 luaconfsCopy
.dsAnchors
.clear();
8098 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8099 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8100 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8101 g_luaconfs
.setState(luaconfsCopy
);
8103 size_t queriesCount
= 0;
8105 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
) {
8108 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8109 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
8113 setLWResult(res
, 0, true, false, true);
8120 vector
<DNSRecord
> ret
;
8121 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8122 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8123 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8124 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
8125 /* com|NS, powerdns.com|NS, powerdns.com|A */
8126 BOOST_CHECK_EQUAL(queriesCount
, 3);
8128 /* again, to test the cache */
8130 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8131 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8132 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
8133 BOOST_REQUIRE_EQUAL(ret
.size(), 0);
8134 /* we don't store empty results */
8135 BOOST_CHECK_EQUAL(queriesCount
, 4);
8138 BOOST_AUTO_TEST_CASE(test_nsec_denial_nowrap
) {
8142 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8144 vector
<DNSRecord
> records
;
8146 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8147 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8151 a.example.org. -> d.example.org. denies the existence of b.example.org.
8153 addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8154 recordContents
.push_back(records
.at(0).d_content
);
8155 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8156 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8159 ContentSigPair pair
;
8160 pair
.records
= recordContents
;
8161 pair
.signatures
= signatureContents
;
8163 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
8165 /* add wildcard denial */
8166 recordContents
.clear();
8167 signatureContents
.clear();
8168 addNSECRecordToLW(DNSName("example.org."), DNSName("+.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8169 recordContents
.push_back(records
.at(0).d_content
);
8170 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8171 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8174 pair
.records
= recordContents
;
8175 pair
.signatures
= signatureContents
;
8176 denialMap
[std::make_pair(DNSName("example.org."), QType::NSEC
)] = pair
;
8178 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
8179 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8181 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
8182 /* let's check that d.example.org. is not denied by this proof */
8183 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8186 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_1
) {
8190 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8192 vector
<DNSRecord
> records
;
8194 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8195 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8198 Wrap case 1 test case:
8199 z.example.org. -> b.example.org. denies the existence of a.example.org.
8201 addNSECRecordToLW(DNSName("z.example.org."), DNSName("b.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8202 recordContents
.push_back(records
.at(0).d_content
);
8203 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8204 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8207 ContentSigPair pair
;
8208 pair
.records
= recordContents
;
8209 pair
.signatures
= signatureContents
;
8211 denialMap
[std::make_pair(DNSName("z.example.org."), QType::NSEC
)] = pair
;
8213 dState denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
8214 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8216 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
8217 /* let's check that d.example.org. is not denied by this proof */
8218 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8221 BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_2
) {
8225 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8227 vector
<DNSRecord
> records
;
8229 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8230 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8233 Wrap case 2 test case:
8234 y.example.org. -> a.example.org. denies the existence of z.example.org.
8236 addNSECRecordToLW(DNSName("y.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8237 recordContents
.push_back(records
.at(0).d_content
);
8238 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8239 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8242 ContentSigPair pair
;
8243 pair
.records
= recordContents
;
8244 pair
.signatures
= signatureContents
;
8246 denialMap
[std::make_pair(DNSName("y.example.org."), QType::NSEC
)] = pair
;
8248 dState denialState
= getDenial(denialMap
, DNSName("z.example.org."), QType::A
, false, false);
8249 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8251 denialState
= getDenial(denialMap
, DNSName("d.example.org."), QType::A
, false, false);
8252 /* let's check that d.example.org. is not denied by this proof */
8253 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8256 BOOST_AUTO_TEST_CASE(test_nsec_denial_only_one_nsec
) {
8260 generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8262 vector
<DNSRecord
> records
;
8264 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8265 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8268 Only one NSEC in the whole zone test case:
8269 a.example.org. -> a.example.org. denies the existence of b.example.org.
8271 addNSECRecordToLW(DNSName("a.example.org."), DNSName("a.example.org"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8272 recordContents
.push_back(records
.at(0).d_content
);
8273 addRRSIG(keys
, records
, DNSName("example.org."), 300);
8274 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8277 ContentSigPair pair
;
8278 pair
.records
= recordContents
;
8279 pair
.signatures
= signatureContents
;
8281 denialMap
[std::make_pair(DNSName("a.example.org."), QType::NSEC
)] = pair
;
8283 dState denialState
= getDenial(denialMap
, DNSName("b.example.org."), QType::A
, false, false);
8284 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8286 denialState
= getDenial(denialMap
, DNSName("a.example.org."), QType::A
, false, false);
8287 /* let's check that d.example.org. is not denied by this proof */
8288 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8291 BOOST_AUTO_TEST_CASE(test_nsec_root_nxd_denial
) {
8295 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8297 vector
<DNSRecord
> records
;
8299 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8300 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8303 The RRSIG from "." denies the existence of anything between a. and c.,
8306 addNSECRecordToLW(DNSName("a."), DNSName("c."), { QType::NS
}, 600, records
);
8307 recordContents
.push_back(records
.at(0).d_content
);
8308 addRRSIG(keys
, records
, DNSName("."), 300);
8309 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8312 ContentSigPair pair
;
8313 pair
.records
= recordContents
;
8314 pair
.signatures
= signatureContents
;
8316 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8318 /* add wildcard denial */
8319 recordContents
.clear();
8320 signatureContents
.clear();
8321 addNSECRecordToLW(DNSName("."), DNSName("+"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8322 recordContents
.push_back(records
.at(0).d_content
);
8323 addRRSIG(keys
, records
, DNSName("."), 300);
8324 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8327 pair
.records
= recordContents
;
8328 pair
.signatures
= signatureContents
;
8329 denialMap
[std::make_pair(DNSName("."), QType::NSEC
)] = pair
;
8331 dState denialState
= getDenial(denialMap
, DNSName("b."), QType::A
, false, false);
8332 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8335 BOOST_AUTO_TEST_CASE(test_nsec_ancestor_nxqtype_denial
) {
8339 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8341 vector
<DNSRecord
> records
;
8343 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8344 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8347 The RRSIG from "." denies the existence of any type except NS at a.
8348 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8349 signer field that is shorter than the owner name of the NSEC RR) it can't
8350 be used to deny anything except the whole name or a DS.
8352 addNSECRecordToLW(DNSName("a."), DNSName("b."), { QType::NS
}, 600, records
);
8353 recordContents
.push_back(records
.at(0).d_content
);
8354 addRRSIG(keys
, records
, DNSName("."), 300);
8355 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8358 ContentSigPair pair
;
8359 pair
.records
= recordContents
;
8360 pair
.signatures
= signatureContents
;
8362 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8364 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8365 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8366 nonexistence of any RRs below that zone cut, which include all RRs at
8367 that (original) owner name other than DS RRs, and all RRs below that
8368 owner name regardless of type.
8371 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, false);
8372 /* no data means the qname/qtype is not denied, because an ancestor
8373 delegation NSEC can only deny the DS */
8374 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8376 /* it can not be used to deny any RRs below that owner name either */
8377 denialState
= getDenial(denialMap
, DNSName("sub.a."), QType::A
, false, false);
8378 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8380 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8381 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8384 BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial
) {
8388 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8390 vector
<DNSRecord
> records
;
8392 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8393 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8396 * RFC 5155 section 8.9:
8397 * If there is an NSEC3 RR present in the response that matches the
8398 * delegation name, then the validator MUST ensure that the NS bit is
8399 * set and that the DS bit is not set in the Type Bit Maps field of the
8403 The RRSIG from "." denies the existence of any type at a.
8404 NS should be set if it was proving an insecure delegation, let's check that
8405 we correctly detect that it's not.
8407 addNSECRecordToLW(DNSName("a."), DNSName("b."), { }, 600, records
);
8408 recordContents
.push_back(records
.at(0).d_content
);
8409 addRRSIG(keys
, records
, DNSName("."), 300);
8410 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8413 ContentSigPair pair
;
8414 pair
.records
= recordContents
;
8415 pair
.signatures
= signatureContents
;
8417 denialMap
[std::make_pair(DNSName("a."), QType::NSEC
)] = pair
;
8419 /* Insecure because the NS is not set, so while it does
8420 denies the DS, it can't prove an insecure delegation */
8421 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8422 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8425 BOOST_AUTO_TEST_CASE(test_nsec_nxqtype_cname
) {
8429 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8431 vector
<DNSRecord
> records
;
8433 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8434 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8436 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::CNAME
}, 600, records
);
8437 recordContents
.push_back(records
.at(0).d_content
);
8438 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8439 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8442 ContentSigPair pair
;
8443 pair
.records
= recordContents
;
8444 pair
.signatures
= signatureContents
;
8446 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8448 /* this NSEC is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8449 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, true, true);
8450 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8453 BOOST_AUTO_TEST_CASE(test_nsec3_nxqtype_cname
) {
8457 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8459 vector
<DNSRecord
> records
;
8461 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8462 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8464 addNSEC3UnhashedRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::CNAME
}, 600, records
);
8465 recordContents
.push_back(records
.at(0).d_content
);
8466 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8467 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8469 ContentSigPair pair
;
8470 pair
.records
= recordContents
;
8471 pair
.signatures
= signatureContents
;
8473 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8476 /* this NSEC3 is not valid to deny a.powerdns.com|A since it states that a CNAME exists */
8477 dState denialState
= getDenial(denialMap
, DNSName("a.powerdns.com."), QType::A
, false, true);
8478 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8481 BOOST_AUTO_TEST_CASE(test_nsec_nxdomain_denial_missing_wildcard
) {
8485 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8487 vector
<DNSRecord
> records
;
8489 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8490 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8492 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("d.powerdns.com"), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8493 recordContents
.push_back(records
.at(0).d_content
);
8494 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8495 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8498 ContentSigPair pair
;
8499 pair
.records
= recordContents
;
8500 pair
.signatures
= signatureContents
;
8502 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8504 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8505 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8508 BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard
) {
8512 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8514 vector
<DNSRecord
> records
;
8516 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8517 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8519 addNSEC3NarrowRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8520 recordContents
.push_back(records
.at(0).d_content
);
8521 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8522 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8524 ContentSigPair pair
;
8525 pair
.records
= recordContents
;
8526 pair
.signatures
= signatureContents
;
8528 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8530 /* Add NSEC3 for the closest encloser */
8531 recordContents
.clear();
8532 signatureContents
.clear();
8534 addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC
}, 600, records
);
8535 recordContents
.push_back(records
.at(0).d_content
);
8536 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8537 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8539 pair
.records
= recordContents
;
8540 pair
.signatures
= signatureContents
;
8541 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8543 dState denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, false, false);
8544 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8547 BOOST_AUTO_TEST_CASE(test_nsec_ent_denial
) {
8551 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8553 vector
<DNSRecord
> records
;
8555 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8556 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8558 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::A
}, 600, records
);
8559 recordContents
.push_back(records
.at(0).d_content
);
8560 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8561 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8564 ContentSigPair pair
;
8565 pair
.records
= recordContents
;
8566 pair
.signatures
= signatureContents
;
8568 denialMap
[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC
)] = pair
;
8570 /* this NSEC is valid to prove a NXQTYPE at c.powerdns.com because it proves that
8572 dState denialState
= getDenial(denialMap
, DNSName("c.powerdns.com."), QType::AAAA
, true, true);
8573 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8575 /* this NSEC is not valid to prove a NXQTYPE at b.powerdns.com,
8576 it could prove a NXDOMAIN if it had an additional wildcard denial */
8577 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::AAAA
, true, true);
8578 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8580 /* this NSEC is not valid to prove a NXQTYPE for QType::A at a.c.powerdns.com either */
8581 denialState
= getDenial(denialMap
, DNSName("a.c.powerdns.com."), QType::A
, true, true);
8582 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8584 /* if we add the wildcard denial proof, we should get a NXDOMAIN proof for b.powerdns.com */
8585 recordContents
.clear();
8586 signatureContents
.clear();
8587 addNSECRecordToLW(DNSName(").powerdns.com."), DNSName("+.powerdns.com."), { }, 600, records
);
8588 recordContents
.push_back(records
.at(0).d_content
);
8589 addRRSIG(keys
, records
, DNSName("powerdns.com."), 300);
8590 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8592 pair
.records
= recordContents
;
8593 pair
.signatures
= signatureContents
;
8594 denialMap
[std::make_pair(DNSName(").powerdns.com."), QType::NSEC
)] = pair
;
8596 denialState
= getDenial(denialMap
, DNSName("b.powerdns.com."), QType::A
, true, false);
8597 BOOST_CHECK_EQUAL(denialState
, NXDOMAIN
);
8600 BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial
) {
8604 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8606 vector
<DNSRecord
> records
;
8608 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8609 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8612 The RRSIG from "." denies the existence of any type except NS at a.
8613 However since it's an ancestor delegation NSEC (NS bit set, SOA bit clear,
8614 signer field that is shorter than the owner name of the NSEC RR) it can't
8615 be used to deny anything except the whole name or a DS.
8617 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::NS
}, 600, records
);
8618 recordContents
.push_back(records
.at(0).d_content
);
8619 addRRSIG(keys
, records
, DNSName("."), 300);
8620 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8622 ContentSigPair pair
;
8623 pair
.records
= recordContents
;
8624 pair
.signatures
= signatureContents
;
8626 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8629 /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
8630 Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
8631 nonexistence of any RRs below that zone cut, which include all RRs at
8632 that (original) owner name other than DS RRs, and all RRs below that
8633 owner name regardless of type.
8636 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8637 /* no data means the qname/qtype is not denied, because an ancestor
8638 delegation NSEC3 can only deny the DS */
8639 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8641 denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8642 BOOST_CHECK_EQUAL(denialState
, NXQTYPE
);
8644 /* it can not be used to deny any RRs below that owner name either */
8645 /* Add NSEC3 for the next closer */
8646 recordContents
.clear();
8647 signatureContents
.clear();
8649 addNSEC3NarrowRecordToLW(DNSName("sub.a."), DNSName("."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC3
}, 600, records
);
8650 recordContents
.push_back(records
.at(0).d_content
);
8651 addRRSIG(keys
, records
, DNSName("."), 300);
8652 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8654 pair
.records
= recordContents
;
8655 pair
.signatures
= signatureContents
;
8656 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8658 /* add wildcard denial */
8659 recordContents
.clear();
8660 signatureContents
.clear();
8662 addNSEC3NarrowRecordToLW(DNSName("*.a."), DNSName("."), { QType::A
, QType::TXT
, QType::RRSIG
, QType::NSEC3
}, 600, records
);
8663 recordContents
.push_back(records
.at(0).d_content
);
8664 addRRSIG(keys
, records
, DNSName("."), 300);
8665 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8667 pair
.records
= recordContents
;
8668 pair
.signatures
= signatureContents
;
8669 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8671 denialState
= getDenial(denialMap
, DNSName("sub.a."), QType::A
, false, true);
8672 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8675 BOOST_AUTO_TEST_CASE(test_nsec3_denial_too_many_iterations
) {
8679 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8681 vector
<DNSRecord
> records
;
8683 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8684 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8686 /* adding a NSEC3 with more iterations that we support */
8687 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { QType::AAAA
}, 600, records
, g_maxNSEC3Iterations
+ 100);
8688 recordContents
.push_back(records
.at(0).d_content
);
8689 addRRSIG(keys
, records
, DNSName("."), 300);
8690 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8692 ContentSigPair pair
;
8693 pair
.records
= recordContents
;
8694 pair
.signatures
= signatureContents
;
8696 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8699 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::A
, false, true);
8700 /* since we refuse to compute more than g_maxNSEC3Iterations iterations, it should be Insecure */
8701 BOOST_CHECK_EQUAL(denialState
, INSECURE
);
8704 BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial
) {
8708 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8710 vector
<DNSRecord
> records
;
8712 vector
<shared_ptr
<DNSRecordContent
>> recordContents
;
8713 vector
<shared_ptr
<RRSIGRecordContent
>> signatureContents
;
8716 * RFC 5155 section 8.9:
8717 * If there is an NSEC3 RR present in the response that matches the
8718 * delegation name, then the validator MUST ensure that the NS bit is
8719 * set and that the DS bit is not set in the Type Bit Maps field of the
8723 The RRSIG from "." denies the existence of any type at a.
8724 NS should be set if it was proving an insecure delegation, let's check that
8725 we correctly detect that it's not.
8727 addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", { }, 600, records
);
8728 recordContents
.push_back(records
.at(0).d_content
);
8729 addRRSIG(keys
, records
, DNSName("."), 300);
8730 signatureContents
.push_back(getRR
<RRSIGRecordContent
>(records
.at(1)));
8732 ContentSigPair pair
;
8733 pair
.records
= recordContents
;
8734 pair
.signatures
= signatureContents
;
8736 denialMap
[std::make_pair(records
.at(0).d_name
, records
.at(0).d_type
)] = pair
;
8739 /* Insecure because the NS is not set, so while it does
8740 denies the DS, it can't prove an insecure delegation */
8741 dState denialState
= getDenial(denialMap
, DNSName("a."), QType::DS
, true, true);
8742 BOOST_CHECK_EQUAL(denialState
, NODATA
);
8745 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_negcache_validity
) {
8746 std::unique_ptr
<SyncRes
> sr
;
8749 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8752 const DNSName
target("com.");
8755 auto luaconfsCopy
= g_luaconfs
.getCopy();
8756 luaconfsCopy
.dsAnchors
.clear();
8757 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8758 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8759 g_luaconfs
.setState(luaconfsCopy
);
8761 size_t queriesCount
= 0;
8763 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
) {
8766 DNSName auth
= domain
;
8769 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8770 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8773 setLWResult(res
, RCode::NoError
, true, false, true);
8774 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
8775 addRRSIG(keys
, res
->d_records
, domain
, 300);
8776 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
8777 addRRSIG(keys
, res
->d_records
, domain
, 1);
8784 const time_t now
= sr
->getNow().tv_sec
;
8785 vector
<DNSRecord
> ret
;
8786 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8787 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8788 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8789 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8790 BOOST_CHECK_EQUAL(queriesCount
, 4);
8792 /* check that the entry has not been negatively cached for longer than the RRSIG validity */
8793 NegCache::NegCacheEntry ne
;
8794 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
8795 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
8796 BOOST_CHECK_EQUAL(ne
.d_ttd
, now
+ 1);
8797 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
8798 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
8799 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
8800 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
8801 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
8803 /* again, to test the cache */
8805 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8806 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8807 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8808 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
8809 BOOST_CHECK_EQUAL(queriesCount
, 4);
8812 BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_cache_validity
) {
8813 std::unique_ptr
<SyncRes
> sr
;
8816 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
8819 const DNSName
target("com.");
8820 const ComboAddress
targetAddr("192.0.2.42");
8823 auto luaconfsCopy
= g_luaconfs
.getCopy();
8824 luaconfsCopy
.dsAnchors
.clear();
8825 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8826 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
8827 g_luaconfs
.setState(luaconfsCopy
);
8829 size_t queriesCount
= 0;
8831 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
) {
8834 DNSName auth
= domain
;
8837 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8838 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
8841 setLWResult(res
, RCode::NoError
, true, false, true);
8842 addRecordToLW(res
, domain
, QType::A
, targetAddr
.toString(), DNSResourceRecord::ANSWER
, 3600);
8843 addRRSIG(keys
, res
->d_records
, domain
, 1);
8850 const time_t now
= sr
->getNow().tv_sec
;
8851 vector
<DNSRecord
> ret
;
8852 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8853 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8854 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8855 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8856 BOOST_CHECK_EQUAL(queriesCount
, 4);
8858 /* check that the entry has not been cached for longer than the RRSIG validity */
8859 const ComboAddress who
;
8860 vector
<DNSRecord
> cached
;
8861 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
8862 BOOST_REQUIRE_EQUAL(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
, &signatures
), 1);
8863 BOOST_REQUIRE_EQUAL(cached
.size(), 1);
8864 BOOST_REQUIRE_EQUAL(signatures
.size(), 1);
8865 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), 1);
8867 /* again, to test the cache */
8869 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8870 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8871 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8872 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8873 BOOST_CHECK_EQUAL(queriesCount
, 4);
8876 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_secure
) {
8878 Validation is optional, and the first query does not ask for it,
8879 so the answer is cached as Indeterminate.
8880 The second query asks for validation, answer should be marked as
8883 std::unique_ptr
<SyncRes
> sr
;
8886 setDNSSECValidation(sr
, DNSSECMode::Process
);
8889 const DNSName
target("com.");
8892 auto luaconfsCopy
= g_luaconfs
.getCopy();
8893 luaconfsCopy
.dsAnchors
.clear();
8894 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
8895 g_luaconfs
.setState(luaconfsCopy
);
8897 size_t queriesCount
= 0;
8899 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
) {
8902 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8903 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8906 if (domain
== target
&& type
== QType::A
) {
8907 setLWResult(res
, 0, true, false, true);
8908 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8909 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
8917 vector
<DNSRecord
> ret
;
8918 /* first query does not require validation */
8919 sr
->setDNSSECValidationRequested(false);
8920 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8921 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8922 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8923 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8924 for (const auto& record
: ret
) {
8925 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8927 BOOST_CHECK_EQUAL(queriesCount
, 1);
8931 /* second one _does_ require validation */
8932 sr
->setDNSSECValidationRequested(true);
8933 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8934 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8935 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
8936 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
8937 for (const auto& record
: ret
) {
8938 BOOST_CHECK(record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
8940 BOOST_CHECK_EQUAL(queriesCount
, 3);
8943 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_insecure
) {
8945 Validation is optional, and the first query does not ask for it,
8946 so the answer is cached as Indeterminate.
8947 The second query asks for validation, answer should be marked as
8950 std::unique_ptr
<SyncRes
> sr
;
8953 setDNSSECValidation(sr
, DNSSECMode::Process
);
8956 const DNSName
target("com.");
8959 auto luaconfsCopy
= g_luaconfs
.getCopy();
8960 luaconfsCopy
.dsAnchors
.clear();
8961 g_luaconfs
.setState(luaconfsCopy
);
8963 size_t queriesCount
= 0;
8965 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
) {
8968 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
8969 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
8972 if (domain
== target
&& type
== QType::A
) {
8973 setLWResult(res
, 0, true, false, true);
8974 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
8982 vector
<DNSRecord
> ret
;
8983 /* first query does not require validation */
8984 sr
->setDNSSECValidationRequested(false);
8985 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8986 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
8987 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
8988 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
8989 for (const auto& record
: ret
) {
8990 BOOST_CHECK(record
.d_type
== QType::A
);
8992 BOOST_CHECK_EQUAL(queriesCount
, 1);
8996 /* second one _does_ require validation */
8997 sr
->setDNSSECValidationRequested(true);
8998 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
8999 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9000 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9001 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9002 for (const auto& record
: ret
) {
9003 BOOST_CHECK(record
.d_type
== QType::A
);
9005 BOOST_CHECK_EQUAL(queriesCount
, 1);
9008 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_bogus
) {
9010 Validation is optional, and the first query does not ask for it,
9011 so the answer is cached as Indeterminate.
9012 The second query asks for validation, answer should be marked as
9015 std::unique_ptr
<SyncRes
> sr
;
9018 setDNSSECValidation(sr
, DNSSECMode::Process
);
9021 const DNSName
target("com.");
9024 auto luaconfsCopy
= g_luaconfs
.getCopy();
9025 luaconfsCopy
.dsAnchors
.clear();
9026 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9027 g_luaconfs
.setState(luaconfsCopy
);
9029 size_t queriesCount
= 0;
9031 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
) {
9034 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9035 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9038 if (domain
== target
&& type
== QType::A
) {
9039 setLWResult(res
, 0, true, false, true);
9040 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
9049 vector
<DNSRecord
> ret
;
9050 /* first query does not require validation */
9051 sr
->setDNSSECValidationRequested(false);
9052 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9053 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9054 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9055 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9056 for (const auto& record
: ret
) {
9057 BOOST_CHECK(record
.d_type
== QType::A
);
9059 BOOST_CHECK_EQUAL(queriesCount
, 1);
9063 /* second one _does_ require validation */
9064 sr
->setDNSSECValidationRequested(true);
9065 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9066 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9067 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9068 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9069 for (const auto& record
: ret
) {
9070 BOOST_CHECK(record
.d_type
== QType::A
);
9072 BOOST_CHECK_EQUAL(queriesCount
, 3);
9075 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_secure
) {
9077 Validation is optional, and the first query does not ask for it,
9078 so the answer is cached as Indeterminate.
9079 The second query asks for validation, answer should be marked as
9082 std::unique_ptr
<SyncRes
> sr
;
9085 setDNSSECValidation(sr
, DNSSECMode::Process
);
9088 const DNSName
target("com.");
9089 const DNSName
cnameTarget("cname-com.");
9092 auto luaconfsCopy
= g_luaconfs
.getCopy();
9093 luaconfsCopy
.dsAnchors
.clear();
9094 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9095 g_luaconfs
.setState(luaconfsCopy
);
9097 size_t queriesCount
= 0;
9099 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
) {
9102 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9103 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9106 if (domain
== target
&& type
== QType::A
) {
9107 setLWResult(res
, 0, true, false, true);
9108 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
9109 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9110 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9111 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9113 } else if (domain
== cnameTarget
&& type
== QType::A
) {
9114 setLWResult(res
, 0, true, false, true);
9115 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9116 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9124 vector
<DNSRecord
> ret
;
9125 /* first query does not require validation */
9126 sr
->setDNSSECValidationRequested(false);
9127 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9128 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9129 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9130 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9131 for (const auto& record
: ret
) {
9132 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
9134 BOOST_CHECK_EQUAL(queriesCount
, 2);
9138 /* second one _does_ require validation */
9139 sr
->setDNSSECValidationRequested(true);
9140 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9141 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9142 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9143 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9144 for (const auto& record
: ret
) {
9145 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
|| record
.d_type
== QType::RRSIG
);
9147 BOOST_CHECK_EQUAL(queriesCount
, 5);
9150 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_insecure
) {
9152 Validation is optional, and the first query does not ask for it,
9153 so the answer is cached as Indeterminate.
9154 The second query asks for validation, answer should be marked as
9157 std::unique_ptr
<SyncRes
> sr
;
9160 setDNSSECValidation(sr
, DNSSECMode::Process
);
9163 const DNSName
target("com.");
9164 const DNSName
cnameTarget("cname-com.");
9167 auto luaconfsCopy
= g_luaconfs
.getCopy();
9168 luaconfsCopy
.dsAnchors
.clear();
9169 g_luaconfs
.setState(luaconfsCopy
);
9171 size_t queriesCount
= 0;
9173 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
) {
9176 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9177 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9180 if (domain
== target
&& type
== QType::A
) {
9181 setLWResult(res
, 0, true, false, true);
9182 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
9183 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9185 } else if (domain
== cnameTarget
&& type
== QType::A
) {
9186 setLWResult(res
, 0, true, false, true);
9187 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9195 vector
<DNSRecord
> ret
;
9196 /* first query does not require validation */
9197 sr
->setDNSSECValidationRequested(false);
9198 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9199 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9200 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9201 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9202 for (const auto& record
: ret
) {
9203 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9205 BOOST_CHECK_EQUAL(queriesCount
, 2);
9209 /* second one _does_ require validation */
9210 sr
->setDNSSECValidationRequested(true);
9211 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9212 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9213 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9214 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9215 for (const auto& record
: ret
) {
9216 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9218 BOOST_CHECK_EQUAL(queriesCount
, 2);
9221 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_bogus
) {
9223 Validation is optional, and the first query does not ask for it,
9224 so the answer is cached as Indeterminate.
9225 The second query asks for validation, answer should be marked as
9228 std::unique_ptr
<SyncRes
> sr
;
9231 setDNSSECValidation(sr
, DNSSECMode::Process
);
9234 const DNSName
target("com.");
9235 const DNSName
cnameTarget("cname-com.");
9238 auto luaconfsCopy
= g_luaconfs
.getCopy();
9239 luaconfsCopy
.dsAnchors
.clear();
9240 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9241 g_luaconfs
.setState(luaconfsCopy
);
9243 size_t queriesCount
= 0;
9245 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
) {
9248 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9249 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9252 if (domain
== target
&& type
== QType::A
) {
9253 setLWResult(res
, 0, true, false, true);
9254 addRecordToLW(res
, target
, QType::CNAME
, cnameTarget
.toString());
9255 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9258 } else if (domain
== cnameTarget
&& type
== QType::A
) {
9259 setLWResult(res
, 0, true, false, true);
9260 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.1");
9269 vector
<DNSRecord
> ret
;
9270 /* first query does not require validation */
9271 sr
->setDNSSECValidationRequested(false);
9272 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9273 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9274 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9275 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9276 for (const auto& record
: ret
) {
9277 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9279 BOOST_CHECK_EQUAL(queriesCount
, 2);
9283 /* second one _does_ require validation */
9284 sr
->setDNSSECValidationRequested(true);
9285 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9286 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9287 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9288 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9289 for (const auto& record
: ret
) {
9290 BOOST_CHECK(record
.d_type
== QType::CNAME
|| record
.d_type
== QType::A
);
9292 BOOST_CHECK_EQUAL(queriesCount
, 5);
9295 BOOST_AUTO_TEST_CASE(test_dnssec_validation_additional_without_rrsig
) {
9297 We get a record from a secure zone in the additional section, without
9298 the corresponding RRSIG. The record should not be marked as authoritative
9299 and should be correctly validated.
9301 std::unique_ptr
<SyncRes
> sr
;
9304 setDNSSECValidation(sr
, DNSSECMode::Process
);
9307 const DNSName
target("com.");
9308 const DNSName
addTarget("nsX.com.");
9311 auto luaconfsCopy
= g_luaconfs
.getCopy();
9312 luaconfsCopy
.dsAnchors
.clear();
9313 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9314 g_luaconfs
.setState(luaconfsCopy
);
9316 size_t queriesCount
= 0;
9318 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
) {
9321 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9322 if (domain
== addTarget
) {
9323 DNSName
auth(domain
);
9324 /* no DS for com, auth will be . */
9326 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
, false);
9328 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9331 if (domain
== target
&& type
== QType::A
) {
9332 setLWResult(res
, 0, true, false, true);
9333 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
9334 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9335 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42", DNSResourceRecord::ADDITIONAL
);
9336 /* no RRSIG for the additional record */
9338 } else if (domain
== addTarget
&& type
== QType::A
) {
9339 setLWResult(res
, 0, true, false, true);
9340 addRecordToLW(res
, addTarget
, QType::A
, "192.0.2.42");
9341 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
9349 vector
<DNSRecord
> ret
;
9350 /* first query for target/A, will pick up the additional record as non-auth / unvalidated */
9351 sr
->setDNSSECValidationRequested(false);
9352 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9353 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9354 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9355 BOOST_CHECK_EQUAL(ret
.size(), 2);
9356 for (const auto& record
: ret
) {
9357 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9359 BOOST_CHECK_EQUAL(queriesCount
, 1);
9362 /* ask for the additional record directly, we should not use
9363 the non-auth one and issue a new query, properly validated */
9364 sr
->setDNSSECValidationRequested(true);
9365 res
= sr
->beginResolve(addTarget
, QType(QType::A
), QClass::IN
, ret
);
9366 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9367 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9368 BOOST_CHECK_EQUAL(ret
.size(), 2);
9369 for (const auto& record
: ret
) {
9370 BOOST_CHECK(record
.d_type
== QType::RRSIG
|| record
.d_type
== QType::A
);
9372 BOOST_CHECK_EQUAL(queriesCount
, 5);
9375 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure
) {
9377 Validation is optional, and the first query does not ask for it,
9378 so the answer is negatively cached as Indeterminate.
9379 The second query asks for validation, answer should be marked as
9382 std::unique_ptr
<SyncRes
> sr
;
9385 setDNSSECValidation(sr
, DNSSECMode::Process
);
9388 const DNSName
target("com.");
9391 auto luaconfsCopy
= g_luaconfs
.getCopy();
9392 luaconfsCopy
.dsAnchors
.clear();
9393 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9394 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9395 g_luaconfs
.setState(luaconfsCopy
);
9397 size_t queriesCount
= 0;
9399 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
) {
9402 DNSName auth
= domain
;
9405 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9406 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9409 setLWResult(res
, RCode::NoError
, true, false, true);
9410 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9411 addRRSIG(keys
, res
->d_records
, domain
, 300);
9412 addNSECRecordToLW(domain
, DNSName("z."), { QType::NSEC
, QType::RRSIG
}, 600, res
->d_records
);
9413 addRRSIG(keys
, res
->d_records
, domain
, 1);
9420 vector
<DNSRecord
> ret
;
9421 /* first query does not require validation */
9422 sr
->setDNSSECValidationRequested(false);
9423 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9424 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9425 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9426 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9427 BOOST_CHECK_EQUAL(queriesCount
, 1);
9428 /* check that the entry has not been negatively cached */
9429 NegCache::NegCacheEntry ne
;
9430 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9431 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9432 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9433 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9434 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9435 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9436 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9439 /* second one _does_ require validation */
9440 sr
->setDNSSECValidationRequested(true);
9441 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9442 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9443 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9444 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9445 BOOST_CHECK_EQUAL(queriesCount
, 4);
9446 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9447 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9448 BOOST_CHECK_EQUAL(ne
.d_validationState
, Secure
);
9449 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9450 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9451 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 1);
9452 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 1);
9455 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure_ds
) {
9457 Validation is optional, and the first query does not ask for it,
9458 so the answer is negatively cached as Indeterminate.
9459 The second query asks for validation, answer should be marked as
9461 The difference with test_dnssec_validation_from_negcache_secure is
9462 that have one more level here, so we are going to look for the proof
9463 that the DS does not exist for the last level. Since there is no cut,
9464 we should accept the fact that the NSEC denies DS and NS both.
9466 std::unique_ptr
<SyncRes
> sr
;
9469 setDNSSECValidation(sr
, DNSSECMode::Process
);
9472 const DNSName
target("www.com.");
9475 auto luaconfsCopy
= g_luaconfs
.getCopy();
9476 luaconfsCopy
.dsAnchors
.clear();
9477 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9478 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9479 g_luaconfs
.setState(luaconfsCopy
);
9481 size_t queriesCount
= 0;
9483 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
) {
9486 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9487 if (domain
== target
) {
9488 /* there is no cut */
9489 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
9491 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
);
9497 vector
<DNSRecord
> ret
;
9498 /* first query does not require validation */
9499 sr
->setDNSSECValidationRequested(false);
9500 int res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9501 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9502 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9503 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9504 BOOST_CHECK_EQUAL(queriesCount
, 1);
9507 /* second one _does_ require validation */
9508 sr
->setDNSSECValidationRequested(true);
9509 res
= sr
->beginResolve(target
, QType(QType::DS
), QClass::IN
, ret
);
9510 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9511 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
9512 BOOST_REQUIRE_EQUAL(ret
.size(), 4);
9513 BOOST_CHECK_EQUAL(queriesCount
, 4);
9516 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_insecure
) {
9518 Validation is optional, and the first query does not ask for it,
9519 so the answer is negatively cached as Indeterminate.
9520 The second query asks for validation, answer should be marked as
9523 std::unique_ptr
<SyncRes
> sr
;
9526 setDNSSECValidation(sr
, DNSSECMode::Process
);
9529 const DNSName
target("com.");
9532 auto luaconfsCopy
= g_luaconfs
.getCopy();
9533 luaconfsCopy
.dsAnchors
.clear();
9534 g_luaconfs
.setState(luaconfsCopy
);
9536 size_t queriesCount
= 0;
9538 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
) {
9541 DNSName auth
= domain
;
9544 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9545 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9548 setLWResult(res
, RCode::NoError
, true, false, true);
9549 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9556 vector
<DNSRecord
> ret
;
9557 /* first query does not require validation */
9558 sr
->setDNSSECValidationRequested(false);
9559 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9560 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9561 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9562 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9563 BOOST_CHECK_EQUAL(queriesCount
, 1);
9564 /* check that the entry has not been negatively cached */
9565 NegCache::NegCacheEntry ne
;
9566 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9567 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9568 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9569 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9570 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9571 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9572 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9575 /* second one _does_ require validation */
9576 sr
->setDNSSECValidationRequested(true);
9577 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9578 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9579 BOOST_CHECK_EQUAL(sr
->getValidationState(), Insecure
);
9580 BOOST_REQUIRE_EQUAL(ret
.size(), 1);
9581 BOOST_CHECK_EQUAL(queriesCount
, 1);
9582 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9583 BOOST_CHECK_EQUAL(ne
.d_validationState
, Insecure
);
9584 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9585 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 0);
9586 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9587 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9590 BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_bogus
) {
9592 Validation is optional, and the first query does not ask for it,
9593 so the answer is negatively cached as Indeterminate.
9594 The second query asks for validation, answer should be marked as
9597 std::unique_ptr
<SyncRes
> sr
;
9600 setDNSSECValidation(sr
, DNSSECMode::Process
);
9603 const DNSName
target("com.");
9606 auto luaconfsCopy
= g_luaconfs
.getCopy();
9607 luaconfsCopy
.dsAnchors
.clear();
9608 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9609 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9610 g_luaconfs
.setState(luaconfsCopy
);
9612 size_t queriesCount
= 0;
9614 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
) {
9617 DNSName auth
= domain
;
9620 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9621 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9624 setLWResult(res
, RCode::NoError
, true, false, true);
9625 addRecordToLW(res
, domain
, QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
9626 addRRSIG(keys
, res
->d_records
, domain
, 300);
9634 vector
<DNSRecord
> ret
;
9635 /* first query does not require validation */
9636 sr
->setDNSSECValidationRequested(false);
9637 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9638 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9639 BOOST_CHECK_EQUAL(sr
->getValidationState(), Indeterminate
);
9640 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9641 BOOST_CHECK_EQUAL(queriesCount
, 1);
9642 NegCache::NegCacheEntry ne
;
9643 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1);
9644 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9645 BOOST_CHECK_EQUAL(ne
.d_validationState
, Indeterminate
);
9646 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9647 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9648 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9649 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9652 /* second one _does_ require validation */
9653 sr
->setDNSSECValidationRequested(true);
9654 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9655 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9656 BOOST_CHECK_EQUAL(sr
->getValidationState(), Bogus
);
9657 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9658 BOOST_CHECK_EQUAL(queriesCount
, 4);
9659 BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage
.negcache
.get(target
, QType(QType::A
), sr
->getNow(), ne
), true);
9660 BOOST_CHECK_EQUAL(ne
.d_validationState
, Bogus
);
9661 BOOST_CHECK_EQUAL(ne
.authoritySOA
.records
.size(), 1);
9662 BOOST_CHECK_EQUAL(ne
.authoritySOA
.signatures
.size(), 1);
9663 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.records
.size(), 0);
9664 BOOST_CHECK_EQUAL(ne
.DNSSECRecords
.signatures
.size(), 0);
9667 BOOST_AUTO_TEST_CASE(test_lowercase_outgoing
) {
9668 g_lowercaseOutgoing
= true;
9669 std::unique_ptr
<SyncRes
> sr
;
9674 vector
<DNSName
> sentOutQnames
;
9676 const DNSName
target("WWW.POWERDNS.COM");
9677 const DNSName
cname("WWW.PowerDNS.org");
9679 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
) {
9681 sentOutQnames
.push_back(domain
);
9683 if (isRootServer(ip
)) {
9684 if (domain
== target
) {
9685 setLWResult(res
, 0, false, false, true);
9686 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
9687 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
9690 if (domain
== cname
) {
9691 setLWResult(res
, 0, false, false, true);
9692 addRecordToLW(res
, "powerdns.org.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
9693 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
9696 } else if (ip
== ComboAddress("192.0.2.1:53")) {
9697 if (domain
== target
) {
9698 setLWResult(res
, 0, true, false, false);
9699 addRecordToLW(res
, domain
, QType::CNAME
, cname
.toString());
9702 } else if (ip
== ComboAddress("192.0.2.2:53")) {
9703 if (domain
== cname
) {
9704 setLWResult(res
, 0, true, false, false);
9705 addRecordToLW(res
, domain
, QType::A
, "127.0.0.1");
9712 vector
<DNSRecord
> ret
;
9713 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
9715 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
9717 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
9718 BOOST_CHECK_EQUAL(ret
[0].d_content
->getZoneRepresentation(), cname
.toString());
9720 BOOST_REQUIRE_EQUAL(sentOutQnames
.size(), 4);
9721 BOOST_CHECK_EQUAL(sentOutQnames
[0].toString(), target
.makeLowerCase().toString());
9722 BOOST_CHECK_EQUAL(sentOutQnames
[1].toString(), target
.makeLowerCase().toString());
9723 BOOST_CHECK_EQUAL(sentOutQnames
[2].toString(), cname
.makeLowerCase().toString());
9724 BOOST_CHECK_EQUAL(sentOutQnames
[3].toString(), cname
.makeLowerCase().toString());
9726 g_lowercaseOutgoing
= false;
9729 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo
) {
9730 std::unique_ptr
<SyncRes
> sr
;
9733 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9736 const DNSName
target("com.");
9737 testkeysset_t keys
, keys2
;
9739 auto luaconfsCopy
= g_luaconfs
.getCopy();
9740 luaconfsCopy
.dsAnchors
.clear();
9741 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9742 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9743 g_luaconfs
.setState(luaconfsCopy
);
9745 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9746 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9747 // But add the existing root key otherwise no RRSIG can be created
9748 auto rootkey
= keys
.find(g_rootdnsname
);
9749 keys2
.insert(*rootkey
);
9751 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
) {
9752 DNSName auth
= domain
;
9754 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9755 if (domain
== target
) {
9756 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9760 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9766 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9767 BOOST_CHECK_EQUAL(state
, Secure
);
9768 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9769 for (const auto& i
: ds
) {
9770 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9774 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_all_sha
) {
9775 std::unique_ptr
<SyncRes
> sr
;
9778 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9781 const DNSName
target("com.");
9782 testkeysset_t keys
, keys2
, keys3
;
9784 auto luaconfsCopy
= g_luaconfs
.getCopy();
9785 luaconfsCopy
.dsAnchors
.clear();
9786 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9787 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9788 g_luaconfs
.setState(luaconfsCopy
);
9790 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9791 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys2
);
9792 // But add the existing root key otherwise no RRSIG can be created
9793 auto rootkey
= keys
.find(g_rootdnsname
);
9794 keys2
.insert(*rootkey
);
9796 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys3
);
9797 // But add the existing root key otherwise no RRSIG can be created
9798 keys3
.insert(*rootkey
);
9800 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
) {
9801 DNSName auth
= domain
;
9803 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9804 if (domain
== target
) {
9805 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9808 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9812 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9818 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9819 BOOST_CHECK_EQUAL(state
, Secure
);
9820 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9821 for (const auto& i
: ds
) {
9822 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
9826 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_two_highest
) {
9827 std::unique_ptr
<SyncRes
> sr
;
9830 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9833 const DNSName
target("com.");
9834 testkeysset_t keys
, keys2
, keys3
;
9836 auto luaconfsCopy
= g_luaconfs
.getCopy();
9837 luaconfsCopy
.dsAnchors
.clear();
9838 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9839 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9840 g_luaconfs
.setState(luaconfsCopy
);
9842 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9843 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys2
);
9844 // But add the existing root key otherwise no RRSIG can be created
9845 auto rootkey
= keys
.find(g_rootdnsname
);
9846 keys2
.insert(*rootkey
);
9848 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys3
);
9849 // But add the existing root key otherwise no RRSIG can be created
9850 keys3
.insert(*rootkey
);
9852 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
) {
9853 DNSName auth
= domain
;
9855 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9856 if (domain
== target
) {
9857 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9860 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys3
) != 1) {
9864 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9870 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9871 BOOST_CHECK_EQUAL(state
, Secure
);
9872 BOOST_REQUIRE_EQUAL(ds
.size(), 2);
9873 for (const auto& i
: ds
) {
9874 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9879 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha384_over_gost
) {
9880 std::unique_ptr
<SyncRes
> sr
;
9883 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9886 const DNSName
target("com.");
9887 testkeysset_t keys
, keys2
;
9889 auto luaconfsCopy
= g_luaconfs
.getCopy();
9890 luaconfsCopy
.dsAnchors
.clear();
9891 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9892 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA384
, keys
);
9893 g_luaconfs
.setState(luaconfsCopy
);
9895 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9896 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9897 // But add the existing root key otherwise no RRSIG can be created
9898 auto rootkey
= keys
.find(g_rootdnsname
);
9899 keys2
.insert(*rootkey
);
9901 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
) {
9902 DNSName auth
= domain
;
9904 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9905 if (domain
== target
) {
9906 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9910 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9916 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9917 BOOST_CHECK_EQUAL(state
, Secure
);
9918 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9919 for (const auto& i
: ds
) {
9920 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA384
);
9924 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_sha256_over_gost
) {
9925 std::unique_ptr
<SyncRes
> sr
;
9928 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9931 const DNSName
target("com.");
9932 testkeysset_t keys
, keys2
;
9934 auto luaconfsCopy
= g_luaconfs
.getCopy();
9935 luaconfsCopy
.dsAnchors
.clear();
9936 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9937 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
);
9938 g_luaconfs
.setState(luaconfsCopy
);
9940 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9941 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9942 // But add the existing root key otherwise no RRSIG can be created
9943 auto rootkey
= keys
.find(g_rootdnsname
);
9944 keys2
.insert(*rootkey
);
9946 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
) {
9947 DNSName auth
= domain
;
9949 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9950 if (domain
== target
) {
9951 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
9955 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
9961 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
9962 BOOST_CHECK_EQUAL(state
, Secure
);
9963 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
9964 for (const auto& i
: ds
) {
9965 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::SHA256
);
9969 BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_prefer_gost_over_sha1
) {
9970 std::unique_ptr
<SyncRes
> sr
;
9973 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
9976 const DNSName
target("com.");
9977 testkeysset_t keys
, keys2
;
9979 auto luaconfsCopy
= g_luaconfs
.getCopy();
9980 luaconfsCopy
.dsAnchors
.clear();
9981 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA256
, keys
, luaconfsCopy
.dsAnchors
);
9982 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::SHA1
, keys
);
9983 g_luaconfs
.setState(luaconfsCopy
);
9985 // As testkeysset_t only contains one DSRecordContent, create another one with a different hash algo
9986 generateKeyMaterial(target
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::GOST
, keys2
);
9987 // But add the existing root key otherwise no RRSIG can be created
9988 auto rootkey
= keys
.find(g_rootdnsname
);
9989 keys2
.insert(*rootkey
);
9991 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
) {
9992 DNSName auth
= domain
;
9994 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
9995 if (domain
== target
) {
9996 if (genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys2
) != 1) {
10000 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
10006 auto state
= sr
->getDSRecords(target
, ds
, false, 0, false);
10007 BOOST_CHECK_EQUAL(state
, Secure
);
10008 BOOST_REQUIRE_EQUAL(ds
.size(), 1);
10009 for (const auto& i
: ds
) {
10010 BOOST_CHECK_EQUAL(i
.d_digesttype
, DNSSECKeeper::GOST
);
10013 #endif // HAVE_BOTAN
10015 BOOST_AUTO_TEST_CASE(test_cname_plus_authority_auth
) {
10016 std::unique_ptr
<SyncRes
> sr
;
10021 const DNSName
target("cname.powerdns.com.");
10022 const DNSName
cnameTarget("cname-target.powerdns.com");
10023 size_t queriesCount
= 0;
10025 sr
->setAsyncCallback([target
, cnameTarget
, &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
) {
10029 if (isRootServer(ip
)) {
10030 setLWResult(res
, 0, false, false, true);
10031 addRecordToLW(res
, DNSName("powerdns.com"), QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
10032 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
10034 } else if (ip
== ComboAddress("192.0.2.1:53")) {
10036 if (domain
== target
) {
10037 setLWResult(res
, 0, true, false, false);
10038 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
10039 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2");
10040 addRecordToLW(res
, DNSName("powerdns.com."), QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 42);
10041 addRecordToLW(res
, DNSName("add.powerdns.com."), QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 42);
10044 else if (domain
== cnameTarget
) {
10045 setLWResult(res
, 0, true, false, false);
10046 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
10055 const time_t now
= sr
->getNow().tv_sec
;
10056 vector
<DNSRecord
> ret
;
10057 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
10058 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
10059 BOOST_REQUIRE_EQUAL(ret
.size(), 2);
10060 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
10061 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
10062 BOOST_CHECK(ret
[1].d_type
== QType::A
);
10063 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
10065 /* check that the NS in authority has been replaced in the cache
10066 with auth=1, but that the part in additional is still not auth */
10067 const ComboAddress who
;
10068 vector
<DNSRecord
> cached
;
10069 bool wasAuth
= false;
10071 BOOST_REQUIRE_GE(t_RC
->get(now
, DNSName("powerdns.com."), QType(QType::NS
), false, &cached
, who
, nullptr, nullptr, nullptr, nullptr, &wasAuth
), 1);
10072 BOOST_CHECK_EQUAL(cached
.size(), 1);
10073 BOOST_CHECK_EQUAL(wasAuth
, true);
10076 BOOST_REQUIRE_GE(t_RC
->get(now
, DNSName("add.powerdns.com."), QType(QType::A
), false, &cached
, who
, nullptr, nullptr, nullptr, nullptr, &wasAuth
), 1);
10077 BOOST_CHECK_EQUAL(cached
.size(), 1);
10078 BOOST_CHECK_EQUAL(wasAuth
, false);
10082 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
10084 - check out of band support
10086 - check preoutquery
10090 BOOST_AUTO_TEST_SUITE_END()