]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursordist/test-syncres_cc.cc
rec: Add and clarify RRSIG labels checks
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc.cc
CommitLineData
30ee601a
RG
1#define BOOST_TEST_DYN_LINK
2#define BOOST_TEST_NO_MAIN
3#include <boost/test/unit_test.hpp>
4
5#include "arguments.hh"
8455425c
RG
6#include "dnssecinfra.hh"
7#include "dnsseckeeper.hh"
30ee601a
RG
8#include "lua-recursor4.hh"
9#include "namespaces.hh"
10#include "rec-lua-conf.hh"
11#include "root-dnssec.hh"
12#include "syncres.hh"
6dfff36f 13#include "utility.hh"
30ee601a
RG
14#include "validate-recursor.hh"
15
30ee601a
RG
16RecursorStats g_stats;
17GlobalStateHolder<LuaConfigItems> g_luaconfs;
f26bf547 18thread_local std::unique_ptr<MemRecursorCache> t_RC{nullptr};
30ee601a
RG
19unsigned int g_numThreads = 1;
20
21/* Fake some required functions we didn't want the trouble to
22 link with */
23ArgvMap &arg()
24{
25 static ArgvMap theArg;
26 return theArg;
27}
28
29int getMTaskerTID()
30{
31 return 0;
32}
33
34bool RecursorLua4::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret)
35{
36 return false;
37}
38
39int 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)
40{
41 return 0;
42}
43
44/* primeHints() is only here for now because it
45 was way too much trouble to link with the real one.
46 We should fix this, empty functions are one thing, but this is
47 bad.
48*/
49
50#include "root-addresses.hh"
51
52void primeHints(void)
53{
54 vector<DNSRecord> nsset;
55 if(!t_RC)
f26bf547 56 t_RC = std::unique_ptr<MemRecursorCache>(new MemRecursorCache());
30ee601a
RG
57
58 DNSRecord arr, aaaarr, nsrr;
59 nsrr.d_name=g_rootdnsname;
60 arr.d_type=QType::A;
61 aaaarr.d_type=QType::AAAA;
62 nsrr.d_type=QType::NS;
63 arr.d_ttl=aaaarr.d_ttl=nsrr.d_ttl=time(nullptr)+3600000;
64
65 for(char c='a';c<='m';++c) {
66 static char templ[40];
67 strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1);
68 templ[sizeof(templ)-1] = '\0';
69 *templ=c;
70 aaaarr.d_name=arr.d_name=DNSName(templ);
71 nsrr.d_content=std::make_shared<NSRecordContent>(DNSName(templ));
72 arr.d_content=std::make_shared<ARecordContent>(ComboAddress(rootIps4[c-'a']));
73 vector<DNSRecord> aset;
74 aset.push_back(arr);
2b984251 75 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
30ee601a
RG
76 if (rootIps6[c-'a'] != NULL) {
77 aaaarr.d_content=std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c-'a']));
78
79 vector<DNSRecord> aaaaset;
80 aaaaset.push_back(aaaarr);
2b984251 81 t_RC->replace(time(0), DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), true);
30ee601a
RG
82 }
83
84 nsset.push_back(nsrr);
85 }
2b984251 86 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
30ee601a
RG
87}
88
89LuaConfigItems::LuaConfigItems()
90{
91 for (const auto &dsRecord : rootDSs) {
92 auto ds=unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(dsRecord)));
93 dsAnchors[g_rootdnsname].insert(*ds);
94 }
95}
96
97/* Some helpers functions */
98
99static void init(bool debug=false)
100{
101 if (debug) {
102 L.setName("test");
103 L.setLoglevel((Logger::Urgency)(6)); // info and up
104 L.disableSyslog(true);
105 L.toConsole(Logger::Info);
106 }
107
108 seedRandom("/dev/urandom");
d6e797b8 109 reportAllTypes();
30ee601a 110
f26bf547 111 t_RC = std::unique_ptr<MemRecursorCache>(new MemRecursorCache());
30ee601a 112
30ee601a
RG
113 SyncRes::s_maxqperq = 50;
114 SyncRes::s_maxtotusec = 1000*7000;
115 SyncRes::s_maxdepth = 40;
116 SyncRes::s_maxnegttl = 3600;
117 SyncRes::s_maxcachettl = 86400;
118 SyncRes::s_packetcachettl = 3600;
119 SyncRes::s_packetcacheservfailttl = 60;
120 SyncRes::s_serverdownmaxfails = 64;
121 SyncRes::s_serverdownthrottletime = 60;
122 SyncRes::s_doIPv6 = true;
e9f9b8ec
RG
123 SyncRes::s_ecsipv4limit = 24;
124 SyncRes::s_ecsipv6limit = 56;
f58c8379 125 SyncRes::s_rootNXTrust = true;
d6e797b8 126 SyncRes::s_minimumTTL = 0;
648bcbd1 127 SyncRes::s_serverID = "PowerDNS Unit Tests Server ID";
9065eb05
RG
128 SyncRes::clearEDNSSubnets();
129 SyncRes::clearEDNSDomains();
130 SyncRes::clearDelegationOnly();
131 SyncRes::clearDontQuery();
648bcbd1 132
a712cb56 133 SyncRes::clearNSSpeeds();
6dfff36f 134 BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0);
a712cb56 135 SyncRes::clearEDNSStatuses();
6dfff36f 136 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0);
a712cb56 137 SyncRes::clearThrottle();
6dfff36f 138 BOOST_CHECK_EQUAL(SyncRes::getThrottledServersSize(), 0);
a712cb56 139 SyncRes::clearFailedServers();
6dfff36f 140 BOOST_CHECK_EQUAL(SyncRes::getFailedServersSize(), 0);
a712cb56 141
648bcbd1
RG
142 auto luaconfsCopy = g_luaconfs.getCopy();
143 luaconfsCopy.dfe.clear();
8455425c
RG
144 luaconfsCopy.dsAnchors.clear();
145 for (const auto &dsRecord : rootDSs) {
146 auto ds=unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(dsRecord)));
147 luaconfsCopy.dsAnchors[g_rootdnsname].insert(*ds);
148 }
149 luaconfsCopy.negAnchors.clear();
648bcbd1
RG
150 g_luaconfs.setState(luaconfsCopy);
151
8455425c 152 g_dnssecmode = DNSSECMode::Off;
895449a5 153 g_dnssecLOG = debug;
8455425c 154
648bcbd1 155 ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Unit Tests";
30ee601a
RG
156}
157
895449a5 158static void initSR(std::unique_ptr<SyncRes>& sr, bool dnssec=false, bool debug=false, time_t fakeNow=0)
30ee601a
RG
159{
160 struct timeval now;
d6e797b8
RG
161 if (fakeNow > 0) {
162 now.tv_sec = fakeNow;
163 now.tv_usec = 0;
164 }
165 else {
166 Utility::gettimeofday(&now, 0);
167 }
168
895449a5
RG
169 init(debug);
170
30ee601a 171 sr = std::unique_ptr<SyncRes>(new SyncRes(now));
895449a5 172 sr->setDoEDNS0(true);
30ee601a 173 sr->setDoDNSSEC(dnssec);
895449a5
RG
174 sr->setLogMode(debug == false ? SyncRes::LogNone : SyncRes::Log);
175
a712cb56
RG
176 SyncRes::setDomainMap(std::make_shared<SyncRes::domainmap_t>());
177 SyncRes::clearNegCache();
30ee601a
RG
178}
179
180static void setLWResult(LWResult* res, int rcode, bool aa=false, bool tc=false, bool edns=false)
181{
182 res->d_rcode = rcode;
183 res->d_aabit = aa;
184 res->d_tcbit = tc;
185 res->d_haveEDNS = edns;
186}
187
8455425c 188static std::shared_ptr<DNSRecordContent> getRecordContent(uint16_t type, const std::string& content)
30ee601a 189{
8455425c 190 std::shared_ptr<DNSRecordContent> result = nullptr;
30ee601a
RG
191
192 if (type == QType::NS) {
8455425c 193 result = std::make_shared<NSRecordContent>(DNSName(content));
30ee601a
RG
194 }
195 else if (type == QType::A) {
8455425c 196 result = std::make_shared<ARecordContent>(ComboAddress(content));
30ee601a 197 }
778bcea6 198 else if (type == QType::AAAA) {
8455425c 199 result = std::make_shared<AAAARecordContent>(ComboAddress(content));
30ee601a 200 }
778bcea6 201 else if (type == QType::CNAME) {
8455425c 202 result = std::make_shared<CNAMERecordContent>(DNSName(content));
778bcea6 203 }
d6e797b8 204 else if (type == QType::OPT) {
8455425c 205 result = std::make_shared<OPTRecordContent>();
d6e797b8 206 }
30ee601a 207 else {
8455425c 208 result = DNSRecordContent::mastermake(type, QClass::IN, content);
30ee601a
RG
209 }
210
8455425c
RG
211 return result;
212}
213
214static void addRecordToList(std::vector<DNSRecord>& records, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl)
215{
216 DNSRecord rec;
217 rec.d_place = place;
218 rec.d_name = name;
219 rec.d_type = type;
220 rec.d_ttl = ttl;
221
222 rec.d_content = getRecordContent(type, content);
223
d6e797b8
RG
224 records.push_back(rec);
225}
226
d6e797b8
RG
227static void addRecordToLW(LWResult* res, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, uint32_t ttl=60)
228{
229 addRecordToList(res->d_records, name, type, content, place, ttl);
30ee601a
RG
230}
231
232static void addRecordToLW(LWResult* res, const std::string& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, uint32_t ttl=60)
233{
234 addRecordToLW(res, DNSName(name), type, content, place, ttl);
235}
236
237static bool isRootServer(const ComboAddress& ip)
238{
8455425c
RG
239 if (ip.isIPv4()) {
240 for (size_t idx = 0; idx < rootIps4Count; idx++) {
241 if (ip.toString() == rootIps4[idx]) {
242 return true;
243 }
30ee601a
RG
244 }
245 }
8455425c
RG
246 else {
247 for (size_t idx = 0; idx < rootIps6Count; idx++) {
248 if (ip.toString() == rootIps6[idx]) {
249 return true;
250 }
30ee601a
RG
251 }
252 }
8455425c 253
30ee601a
RG
254 return false;
255}
256
3d5ebf10 257static 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)
8455425c
RG
258{
259 time_t now = time(nullptr);
260 DNSKEYRecordContent drc = dpk.getDNSKEY();
261 const std::shared_ptr<DNSCryptoKeyEngine> rc = dpk.getKey();
262
263 rrc.d_type = signQType;
264 rrc.d_labels = signQName.countLabels() - signQName.isWildcard();
265 rrc.d_originalttl = signTTL;
812c3a69 266 rrc.d_siginception = now - 10;
8455425c
RG
267 rrc.d_sigexpire = now + sigValidity;
268 rrc.d_signer = signer;
269 rrc.d_tag = 0;
270 rrc.d_tag = drc.getTag();
3d5ebf10 271 rrc.d_algorithm = algo ? *algo : drc.d_algorithm;
8455425c
RG
272
273 std::string msg = getMessageForRRSET(signQName, rrc, toSign);
274
275 rrc.d_signature = rc->sign(msg);
276}
277
b7f378d1
RG
278typedef std::unordered_map<DNSName, std::pair<DNSSECPrivateKey, DSRecordContent> > testkeysset_t;
279
2b984251 280static void 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)
8455425c
RG
281{
282 if (records.empty()) {
283 return;
284 }
285
286 const auto it = keys.find(signer);
287 if (it == keys.cend()) {
288 throw std::runtime_error("No DNSKEY found for " + signer.toString() + ", unable to compute the requested RRSIG");
289 }
290
291 size_t recordsCount = records.size();
292 const DNSName& name = records[recordsCount-1].d_name;
293 const uint16_t type = records[recordsCount-1].d_type;
294
295 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
296 for (const auto record : records) {
297 if (record.d_name == name && record.d_type == type) {
298 recordcontents.push_back(record.d_content);
299 }
300 }
301
302 RRSIGRecordContent rrc;
2b984251 303 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);
3d5ebf10
RG
304 if (broken) {
305 rrc.d_signature[0] ^= 42;
306 }
8455425c
RG
307
308 DNSRecord rec;
309 rec.d_place = records[recordsCount-1].d_place;
310 rec.d_name = records[recordsCount-1].d_name;
311 rec.d_type = QType::RRSIG;
312 rec.d_ttl = sigValidity;
313
314 rec.d_content = std::make_shared<RRSIGRecordContent>(rrc);
315 records.push_back(rec);
316}
317
b7f378d1 318static void addDNSKEY(const testkeysset_t& keys, const DNSName& signer, uint32_t ttl, std::vector<DNSRecord>& records)
8455425c
RG
319{
320 const auto it = keys.find(signer);
321 if (it == keys.cend()) {
322 throw std::runtime_error("No DNSKEY found for " + signer.toString());
323 }
324
325 DNSRecord rec;
326 rec.d_place = DNSResourceRecord::ANSWER;
327 rec.d_name = signer;
328 rec.d_type = QType::DNSKEY;
329 rec.d_ttl = ttl;
330
b7f378d1 331 rec.d_content = std::make_shared<DNSKEYRecordContent>(it->second.first.getDNSKEY());
8455425c
RG
332 records.push_back(rec);
333}
334
a53e8fe3 335static void addDS(const DNSName& domain, uint32_t ttl, std::vector<DNSRecord>& records, const testkeysset_t& keys, DNSResourceRecord::Place place=DNSResourceRecord::AUTHORITY)
8455425c 336{
b7f378d1
RG
337 const auto it = keys.find(domain);
338 if (it == keys.cend()) {
8455425c
RG
339 return;
340 }
341
b7f378d1
RG
342 DNSRecord rec;
343 rec.d_name = domain;
344 rec.d_type = QType::DS;
a53e8fe3 345 rec.d_place = place;
b7f378d1
RG
346 rec.d_ttl = ttl;
347 rec.d_content = std::make_shared<DSRecordContent>(it->second.second);
8455425c 348
b7f378d1 349 records.push_back(rec);
8455425c
RG
350}
351
352static void addNSECRecordToLW(const DNSName& domain, const DNSName& next, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records)
353{
354 NSECRecordContent nrc;
355 nrc.d_next = next;
356 nrc.d_set = types;
357
358 DNSRecord rec;
359 rec.d_name = domain;
360 rec.d_ttl = ttl;
361 rec.d_type = QType::NSEC;
362 rec.d_content = std::make_shared<NSECRecordContent>(nrc);
363 rec.d_place = DNSResourceRecord::AUTHORITY;
364
365 records.push_back(rec);
366}
367
b7f378d1 368static void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys)
8455425c
RG
369{
370 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(algo));
b7f378d1 371 dcke->create((algo <= 10) ? 2048 : dcke->getBits());
8455425c
RG
372 DNSSECPrivateKey dpk;
373 dpk.d_flags = 256;
374 dpk.setKey(dcke);
8455425c 375 DSRecordContent ds = makeDSFromDNSKey(name, dpk.getDNSKEY(), digest);
b7f378d1
RG
376 keys[name] = std::pair<DNSSECPrivateKey,DSRecordContent>(dpk,ds);
377}
378
379static void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys, map<DNSName,dsmap_t>& dsAnchors)
380{
381 generateKeyMaterial(name, algo, digest, keys);
382 dsAnchors[name].insert(keys[name].second);
8455425c
RG
383}
384
30ee601a
RG
385/* Real tests */
386
387BOOST_AUTO_TEST_SUITE(syncres_cc)
388
389BOOST_AUTO_TEST_CASE(test_root_primed) {
390 std::unique_ptr<SyncRes> sr;
895449a5 391 initSR(sr);
30ee601a
RG
392
393 primeHints();
895449a5 394
4d2be65d 395 const DNSName target("a.root-servers.net.");
30ee601a 396
4d2be65d 397 /* we are primed, we should be able to resolve A a.root-servers.net. without any query */
30ee601a 398 vector<DNSRecord> ret;
4d2be65d 399 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 400 BOOST_CHECK_EQUAL(res, RCode::NoError);
4d2be65d
RG
401 BOOST_REQUIRE_EQUAL(ret.size(), 1);
402 BOOST_CHECK(ret[0].d_type == QType::A);
403 BOOST_CHECK_EQUAL(ret[0].d_name, target);
404
405 ret.clear();
406 res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
b7f378d1
RG
407 BOOST_CHECK_EQUAL(res, RCode::NoError);
408 BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate);
4d2be65d
RG
409 BOOST_REQUIRE_EQUAL(ret.size(), 1);
410 BOOST_CHECK(ret[0].d_type == QType::AAAA);
411 BOOST_CHECK_EQUAL(ret[0].d_name, target);
4d2be65d
RG
412}
413
414BOOST_AUTO_TEST_CASE(test_root_primed_ns) {
415 std::unique_ptr<SyncRes> sr;
895449a5 416 initSR(sr);
4d2be65d
RG
417
418 primeHints();
419 const DNSName target(".");
420
421 /* we are primed, but we should not be able to NS . without any query
422 because the . NS entry is not stored as authoritative */
423
424 size_t queriesCount = 0;
425
426 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) {
427 queriesCount++;
428
429 if (domain == target && type == QType::NS) {
430
431 setLWResult(res, 0, true, false, true);
8455425c 432 char addr[] = "a.root-servers.net.";
4d2be65d 433 for (char idx = 'a'; idx <= 'm'; idx++) {
8455425c
RG
434 addr[0] = idx;
435 addRecordToLW(res, g_rootdnsname, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
4d2be65d
RG
436 }
437
438 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
439 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
440
441 return 1;
442 }
443
444 return 0;
445 });
446
447 vector<DNSRecord> ret;
448 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1 449 BOOST_CHECK_EQUAL(res, RCode::NoError);
4d2be65d
RG
450 BOOST_REQUIRE_EQUAL(ret.size(), 13);
451 BOOST_CHECK_EQUAL(queriesCount, 1);
30ee601a
RG
452}
453
454BOOST_AUTO_TEST_CASE(test_root_not_primed) {
455 std::unique_ptr<SyncRes> sr;
895449a5 456 initSR(sr);
30ee601a
RG
457
458 size_t queriesCount = 0;
459
460 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) {
461 queriesCount++;
462
463 if (domain == g_rootdnsname && type == QType::NS) {
464 setLWResult(res, 0, true, false, true);
465 addRecordToLW(res, g_rootdnsname, QType::NS, "a.root-servers.net.", DNSResourceRecord::ANSWER, 3600);
466 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
467 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
468
469 return 1;
470 }
471
472 return 0;
473 });
474
475 /* we are not primed yet, so SyncRes will have to call primeHints()
476 then call getRootNS(), for which at least one of the root servers needs to answer */
477 vector<DNSRecord> ret;
478 int res = sr->beginResolve(DNSName("."), QType(QType::NS), QClass::IN, ret);
b7f378d1 479 BOOST_CHECK_EQUAL(res, RCode::NoError);
30ee601a
RG
480 BOOST_CHECK_EQUAL(ret.size(), 1);
481 BOOST_CHECK_EQUAL(queriesCount, 2);
482}
483
484BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response) {
485 std::unique_ptr<SyncRes> sr;
895449a5 486 initSR(sr);
30ee601a
RG
487 std::set<ComboAddress> downServers;
488
489 /* we are not primed yet, so SyncRes will have to call primeHints()
490 then call getRootNS(), for which at least one of the root servers needs to answer.
491 None will, so it should ServFail.
492 */
493 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) {
494
495 downServers.insert(ip);
496 return 0;
497 });
498
499 vector<DNSRecord> ret;
500 int res = sr->beginResolve(DNSName("."), QType(QType::NS), QClass::IN, ret);
f58c8379 501 BOOST_CHECK_EQUAL(res, RCode::ServFail);
30ee601a
RG
502 BOOST_CHECK_EQUAL(ret.size(), 0);
503 BOOST_CHECK(downServers.size() > 0);
504 /* we explicitly refuse to mark the root servers down */
505 for (const auto& server : downServers) {
a712cb56 506 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 0);
30ee601a
RG
507 }
508}
509
510BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback) {
511 std::unique_ptr<SyncRes> sr;
895449a5 512 initSR(sr);
30ee601a
RG
513
514 ComboAddress noEDNSServer;
515 size_t queriesWithEDNS = 0;
516 size_t queriesWithoutEDNS = 0;
517
518 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) {
519 if (EDNS0Level != 0) {
520 queriesWithEDNS++;
521 noEDNSServer = ip;
522
523 setLWResult(res, RCode::FormErr);
524 return 1;
525 }
526
527 queriesWithoutEDNS++;
528
529 if (domain == DNSName("powerdns.com") && type == QType::A && !doTCP) {
530 setLWResult(res, 0, true, false, false);
531 addRecordToLW(res, domain, QType::A, "192.0.2.1");
532 return 1;
533 }
534
535 return 0;
536 });
537
538 primeHints();
539
540 /* fake that the root NS doesn't handle EDNS, check that we fallback */
541 vector<DNSRecord> ret;
542 int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
b7f378d1 543 BOOST_CHECK_EQUAL(res, RCode::NoError);
30ee601a
RG
544 BOOST_CHECK_EQUAL(ret.size(), 1);
545 BOOST_CHECK_EQUAL(queriesWithEDNS, 1);
546 BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1);
a712cb56
RG
547 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 1);
548 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer), SyncRes::EDNSStatus::NOEDNS);
30ee601a
RG
549}
550
551BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback) {
552 std::unique_ptr<SyncRes> sr;
895449a5 553 initSR(sr);
30ee601a
RG
554
555 size_t queriesWithEDNS = 0;
556 size_t queriesWithoutEDNS = 0;
557
558 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) {
559 if (EDNS0Level != 0) {
560 queriesWithEDNS++;
561 setLWResult(res, RCode::NotImp);
562 return 1;
563 }
564
565 queriesWithoutEDNS++;
566
567 if (domain == DNSName("powerdns.com") && type == QType::A && !doTCP) {
568 setLWResult(res, 0, true, false, false);
569 addRecordToLW(res, domain, QType::A, "192.0.2.1");
570 return 1;
571 }
572
573 return 0;
574 });
575
576 primeHints();
577
578 /* fake that the NS doesn't handle EDNS, check that we fallback */
579 vector<DNSRecord> ret;
580 int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
b7f378d1 581 BOOST_CHECK_EQUAL(res, RCode::NoError);
30ee601a
RG
582 BOOST_CHECK_EQUAL(ret.size(), 1);
583 BOOST_CHECK_EQUAL(queriesWithEDNS, 1);
584 BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1);
585}
586
587BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp) {
588 std::unique_ptr<SyncRes> sr;
895449a5 589 initSR(sr);
30ee601a
RG
590
591 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) {
592 if (!doTCP) {
593 setLWResult(res, 0, false, true, false);
594 return 1;
595 }
596 if (domain == DNSName("powerdns.com") && type == QType::A && doTCP) {
597 setLWResult(res, 0, true, false, false);
598 addRecordToLW(res, domain, QType::A, "192.0.2.1");
599 return 1;
600 }
601
602 return 0;
603 });
604
605 primeHints();
606
607 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
608 vector<DNSRecord> ret;
609 int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
b7f378d1 610 BOOST_CHECK_EQUAL(res, RCode::NoError);
30ee601a
RG
611}
612
3337c2f7
RG
613BOOST_AUTO_TEST_CASE(test_tc_over_tcp) {
614 std::unique_ptr<SyncRes> sr;
895449a5 615 initSR(sr);
3337c2f7
RG
616
617 size_t tcpQueriesCount = 0;
618
619 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) {
620 if (!doTCP) {
621 setLWResult(res, 0, true, true, false);
622 return 1;
623 }
624
625 /* first TCP query is answered with a TC response */
626 tcpQueriesCount++;
627 if (tcpQueriesCount == 1) {
628 setLWResult(res, 0, true, true, false);
629 }
630 else {
631 setLWResult(res, 0, true, false, false);
632 }
633
634 addRecordToLW(res, domain, QType::A, "192.0.2.1");
635 return 1;
636 });
637
638 primeHints();
639
640 vector<DNSRecord> ret;
641 int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
b7f378d1 642 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
643 BOOST_CHECK_EQUAL(tcpQueriesCount, 2);
644}
645
30ee601a
RG
646BOOST_AUTO_TEST_CASE(test_all_nss_down) {
647 std::unique_ptr<SyncRes> sr;
895449a5 648 initSR(sr);
30ee601a
RG
649 std::set<ComboAddress> downServers;
650
651 primeHints();
652
653 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) {
654
655 if (isRootServer(ip)) {
8455425c 656 setLWResult(res, 0, false, false, true);
30ee601a
RG
657 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
658 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
659 addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600);
660 return 1;
661 }
662 else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) {
8455425c 663 setLWResult(res, 0, false, false, true);
30ee601a
RG
664 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
665 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
666 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800);
667 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800);
668 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800);
669 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800);
670 return 1;
671 }
672 else {
673 downServers.insert(ip);
674 return 0;
675 }
676 });
677
ccb07d93
RG
678 DNSName target("powerdns.com.");
679
30ee601a 680 vector<DNSRecord> ret;
ccb07d93 681 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
f58c8379 682 BOOST_CHECK_EQUAL(res, RCode::ServFail);
30ee601a
RG
683 BOOST_CHECK_EQUAL(ret.size(), 0);
684 BOOST_CHECK_EQUAL(downServers.size(), 4);
685
686 for (const auto& server : downServers) {
a712cb56
RG
687 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 1);
688 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server, target, QType::A));
30ee601a
RG
689 }
690}
691
648bcbd1
RG
692BOOST_AUTO_TEST_CASE(test_all_nss_network_error) {
693 std::unique_ptr<SyncRes> sr;
895449a5 694 initSR(sr);
648bcbd1
RG
695 std::set<ComboAddress> downServers;
696
697 primeHints();
698
699 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) {
700
701 if (isRootServer(ip)) {
8455425c 702 setLWResult(res, 0, false, false, true);
648bcbd1
RG
703 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
704 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
705 addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600);
706 return 1;
707 }
708 else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) {
8455425c 709 setLWResult(res, 0, false, false, true);
648bcbd1
RG
710 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
711 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
712 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800);
713 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800);
714 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800);
715 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800);
716 return 1;
717 }
718 else {
719 downServers.insert(ip);
720 return -1;
721 }
722 });
723
724 /* exact same test than the previous one, except instead of a time out we fake a network error */
725 DNSName target("powerdns.com.");
726
727 vector<DNSRecord> ret;
728 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
729 BOOST_CHECK_EQUAL(res, RCode::ServFail);
730 BOOST_CHECK_EQUAL(ret.size(), 0);
731 BOOST_CHECK_EQUAL(downServers.size(), 4);
732
733 for (const auto& server : downServers) {
a712cb56
RG
734 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 1);
735 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server, target, QType::A));
736;
648bcbd1
RG
737 }
738}
739
740BOOST_AUTO_TEST_CASE(test_os_limit_errors) {
741 std::unique_ptr<SyncRes> sr;
895449a5 742 initSR(sr);
648bcbd1
RG
743 std::set<ComboAddress> downServers;
744
745 primeHints();
746
747 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) {
748
749 if (isRootServer(ip)) {
8455425c 750 setLWResult(res, 0, false, false, true);
648bcbd1
RG
751 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
752 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
753 addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600);
754 return 1;
755 }
756 else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) {
8455425c 757 setLWResult(res, 0, false, false, true);
648bcbd1
RG
758 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
759 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
760 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800);
761 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800);
762 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800);
763 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800);
764 return 1;
765 }
766 else {
767 if (downServers.size() < 3) {
768 /* only the last one will answer */
769 downServers.insert(ip);
770 return -2;
771 }
772 else {
773 setLWResult(res, 0, true, false, true);
774 addRecordToLW(res, "powerdns.com.", QType::A, "192.0.2.42");
775 return 1;
776 }
777 }
778 });
779
780 DNSName target("powerdns.com.");
781
782 vector<DNSRecord> ret;
783 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 784 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
785 BOOST_CHECK_EQUAL(ret.size(), 1);
786 BOOST_CHECK_EQUAL(downServers.size(), 3);
787
788 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
789 for (const auto& server : downServers) {
a712cb56
RG
790 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 0);
791 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server, target, QType::A));
648bcbd1
RG
792 }
793}
794
30ee601a
RG
795BOOST_AUTO_TEST_CASE(test_glued_referral) {
796 std::unique_ptr<SyncRes> sr;
895449a5 797 initSR(sr);
30ee601a
RG
798
799 primeHints();
800
801 const DNSName target("powerdns.com.");
802
803 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) {
804 /* this will cause issue with qname minimization if we ever implement it */
805 if (domain != target) {
806 return 0;
807 }
808
809 if (isRootServer(ip)) {
8455425c 810 setLWResult(res, 0, false, false, true);
30ee601a
RG
811 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
812 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
813 addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600);
814 return 1;
815 }
816 else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) {
8455425c 817 setLWResult(res, 0, false, false, true);
30ee601a
RG
818 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
819 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
820 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800);
821 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800);
822 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800);
823 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800);
824 return 1;
825 }
826 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")) {
827 setLWResult(res, 0, true, false, true);
828 addRecordToLW(res, target, QType::A, "192.0.2.4");
829 return 1;
830 }
831 else {
832 return 0;
833 }
834 });
835
836 vector<DNSRecord> ret;
837 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 838 BOOST_CHECK_EQUAL(res, RCode::NoError);
30ee601a 839 BOOST_REQUIRE_EQUAL(ret.size(), 1);
e9f9b8ec 840 BOOST_CHECK(ret[0].d_type == QType::A);
30ee601a
RG
841 BOOST_CHECK_EQUAL(ret[0].d_name, target);
842}
843
844BOOST_AUTO_TEST_CASE(test_glueless_referral) {
845 std::unique_ptr<SyncRes> sr;
895449a5 846 initSR(sr);
30ee601a
RG
847
848 primeHints();
849
850 const DNSName target("powerdns.com.");
851
852 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) {
853
854 if (isRootServer(ip)) {
8455425c 855 setLWResult(res, 0, false, false, true);
30ee601a
RG
856
857 if (domain.isPartOf(DNSName("com."))) {
858 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
859 } else if (domain.isPartOf(DNSName("org."))) {
860 addRecordToLW(res, "org.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
861 }
862 else {
863 setLWResult(res, RCode::NXDomain, false, false, true);
864 return 1;
865 }
866
867 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
868 addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600);
869 return 1;
870 }
871 else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) {
872 if (domain == target) {
8455425c 873 setLWResult(res, 0, false, false, true);
30ee601a
RG
874 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
875 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
876 return 1;
877 }
878 else if (domain == DNSName("pdns-public-ns1.powerdns.org.")) {
879 setLWResult(res, 0, true, false, true);
880 addRecordToLW(res, "pdns-public-ns1.powerdns.org.", QType::A, "192.0.2.2");
881 addRecordToLW(res, "pdns-public-ns1.powerdns.org.", QType::AAAA, "2001:DB8::2");
882 return 1;
883 }
884 else if (domain == DNSName("pdns-public-ns2.powerdns.org.")) {
885 setLWResult(res, 0, true, false, true);
886 addRecordToLW(res, "pdns-public-ns2.powerdns.org.", QType::A, "192.0.2.3");
887 addRecordToLW(res, "pdns-public-ns2.powerdns.org.", QType::AAAA, "2001:DB8::3");
888 return 1;
889 }
890
891 setLWResult(res, RCode::NXDomain, false, false, true);
892 return 1;
893 }
894 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")) {
895 setLWResult(res, 0, true, false, true);
896 addRecordToLW(res, target, QType::A, "192.0.2.4");
897 return 1;
898 }
899 else {
900 return 0;
901 }
902 });
903
904 vector<DNSRecord> ret;
905 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 906 BOOST_CHECK_EQUAL(res, RCode::NoError);
30ee601a 907 BOOST_REQUIRE_EQUAL(ret.size(), 1);
e9f9b8ec 908 BOOST_CHECK(ret[0].d_type == QType::A);
30ee601a
RG
909 BOOST_CHECK_EQUAL(ret[0].d_name, target);
910}
911
e9f9b8ec
RG
912BOOST_AUTO_TEST_CASE(test_edns_submask_by_domain) {
913 std::unique_ptr<SyncRes> sr;
895449a5 914 initSR(sr);
e9f9b8ec
RG
915
916 primeHints();
917
918 const DNSName target("powerdns.com.");
9065eb05 919 SyncRes::addEDNSDomain(target);
e9f9b8ec
RG
920
921 EDNSSubnetOpts incomingECS;
922 incomingECS.source = Netmask("192.0.2.128/32");
923 sr->setIncomingECSFound(true);
924 sr->setIncomingECS(incomingECS);
925
926 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) {
927
928 BOOST_REQUIRE(srcmask);
929 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
930 return 0;
931 });
932
933 vector<DNSRecord> ret;
934 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
f58c8379 935 BOOST_CHECK_EQUAL(res, RCode::ServFail);
e9f9b8ec
RG
936}
937
938BOOST_AUTO_TEST_CASE(test_edns_submask_by_addr) {
939 std::unique_ptr<SyncRes> sr;
895449a5 940 initSR(sr);
e9f9b8ec
RG
941
942 primeHints();
943
944 const DNSName target("powerdns.com.");
9065eb05 945 SyncRes::addEDNSSubnet(Netmask("192.0.2.1/32"));
e9f9b8ec
RG
946
947 EDNSSubnetOpts incomingECS;
948 incomingECS.source = Netmask("2001:DB8::FF/128");
949 sr->setIncomingECSFound(true);
950 sr->setIncomingECS(incomingECS);
951
952 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) {
953
954 if (isRootServer(ip)) {
955 BOOST_REQUIRE(!srcmask);
956
8455425c 957 setLWResult(res, 0, false, false, true);
e9f9b8ec
RG
958 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
959 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
960 return 1;
961 } else if (ip == ComboAddress("192.0.2.1:53")) {
962
963 BOOST_REQUIRE(srcmask);
964 BOOST_CHECK_EQUAL(srcmask->toString(), "2001:db8::/56");
965
966 setLWResult(res, 0, true, false, false);
967 addRecordToLW(res, domain, QType::A, "192.0.2.2");
968 return 1;
969 }
970
971 return 0;
972 });
973
974 vector<DNSRecord> ret;
975 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 976 BOOST_CHECK_EQUAL(res, RCode::NoError);
778bcea6
RG
977 BOOST_REQUIRE_EQUAL(ret.size(), 1);
978 BOOST_CHECK(ret[0].d_type == QType::A);
979 BOOST_CHECK_EQUAL(ret[0].d_name, target);
980}
981
982BOOST_AUTO_TEST_CASE(test_following_cname) {
983 std::unique_ptr<SyncRes> sr;
895449a5 984 initSR(sr);
778bcea6
RG
985
986 primeHints();
987
988 const DNSName target("cname.powerdns.com.");
989 const DNSName cnameTarget("cname-target.powerdns.com");
990
991 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) {
992
993 if (isRootServer(ip)) {
8455425c 994 setLWResult(res, 0, false, false, true);
778bcea6
RG
995 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
996 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
997 return 1;
998 } else if (ip == ComboAddress("192.0.2.1:53")) {
999
1000 if (domain == target) {
1001 setLWResult(res, 0, true, false, false);
1002 addRecordToLW(res, domain, QType::CNAME, cnameTarget.toString());
1003 return 1;
1004 }
1005 else if (domain == cnameTarget) {
1006 setLWResult(res, 0, true, false, false);
1007 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1008 }
1009
1010 return 1;
1011 }
1012
1013 return 0;
1014 });
1015
1016 vector<DNSRecord> ret;
1017 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1018 BOOST_CHECK_EQUAL(res, RCode::NoError);
778bcea6
RG
1019 BOOST_REQUIRE_EQUAL(ret.size(), 2);
1020 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1021 BOOST_CHECK_EQUAL(ret[0].d_name, target);
1022 BOOST_CHECK(ret[1].d_type == QType::A);
1023 BOOST_CHECK_EQUAL(ret[1].d_name, cnameTarget);
1024}
1025
4fff116b
RG
1026BOOST_AUTO_TEST_CASE(test_included_poisonous_cname) {
1027 std::unique_ptr<SyncRes> sr;
895449a5 1028 initSR(sr);
4fff116b
RG
1029
1030 primeHints();
1031
1032 /* In this test we directly get the NS server for cname.powerdns.com.,
1033 and we don't know whether it's also authoritative for
1034 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1035 the additional A record for cname-target.powerdns.com. */
1036 const DNSName target("cname.powerdns.com.");
1037 const DNSName cnameTarget("cname-target.powerdns.com");
1038
1039 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) {
1040
1041 if (isRootServer(ip)) {
1042
8455425c 1043 setLWResult(res, 0, false, false, true);
4fff116b
RG
1044
1045 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1046 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1047 return 1;
1048 } else if (ip == ComboAddress("192.0.2.1:53")) {
1049
1050 if (domain == target) {
1051 setLWResult(res, 0, true, false, false);
1052 addRecordToLW(res, domain, QType::CNAME, cnameTarget.toString());
1053 addRecordToLW(res, cnameTarget, QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL);
1054 return 1;
1055 } else if (domain == cnameTarget) {
1056 setLWResult(res, 0, true, false, false);
1057 addRecordToLW(res, cnameTarget, QType::A, "192.0.2.3");
1058 return 1;
1059 }
1060
1061 return 1;
1062 }
1063
1064 return 0;
1065 });
1066
1067 vector<DNSRecord> ret;
1068 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1069 BOOST_CHECK_EQUAL(res, RCode::NoError);
4fff116b
RG
1070 BOOST_REQUIRE_EQUAL(ret.size(), 2);
1071 BOOST_REQUIRE(ret[0].d_type == QType::CNAME);
1072 BOOST_CHECK_EQUAL(ret[0].d_name, target);
1073 BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget(), cnameTarget);
1074 BOOST_REQUIRE(ret[1].d_type == QType::A);
1075 BOOST_CHECK_EQUAL(ret[1].d_name, cnameTarget);
1076 BOOST_CHECK(getRR<ARecordContent>(ret[1])->getCA() == ComboAddress("192.0.2.3"));
1077}
1078
778bcea6
RG
1079BOOST_AUTO_TEST_CASE(test_cname_loop) {
1080 std::unique_ptr<SyncRes> sr;
895449a5 1081 initSR(sr);
778bcea6
RG
1082
1083 primeHints();
1084
1085 size_t count = 0;
1086 const DNSName target("cname.powerdns.com.");
1087
1088 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) {
1089
1090 count++;
1091
1092 if (isRootServer(ip)) {
778bcea6 1093
8455425c 1094 setLWResult(res, 0, false, false, true);
778bcea6
RG
1095 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1096 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1097 return 1;
1098 } else if (ip == ComboAddress("192.0.2.1:53")) {
1099
1100 if (domain == target) {
1101 setLWResult(res, 0, true, false, false);
1102 addRecordToLW(res, domain, QType::CNAME, domain.toString());
1103 return 1;
1104 }
1105
1106 return 1;
1107 }
1108
1109 return 0;
1110 });
1111
1112 vector<DNSRecord> ret;
1113 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
f58c8379
RG
1114 BOOST_CHECK_EQUAL(res, RCode::ServFail);
1115 BOOST_CHECK_GT(ret.size(), 0);
778bcea6 1116 BOOST_CHECK_EQUAL(count, 2);
e9f9b8ec
RG
1117}
1118
4fff116b
RG
1119BOOST_AUTO_TEST_CASE(test_cname_depth) {
1120 std::unique_ptr<SyncRes> sr;
895449a5 1121 initSR(sr);
4fff116b
RG
1122
1123 primeHints();
1124
1125 size_t depth = 0;
1126 const DNSName target("cname.powerdns.com.");
1127
1128 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) {
1129
1130 if (isRootServer(ip)) {
4fff116b 1131
8455425c 1132 setLWResult(res, 0, false, false, true);
4fff116b
RG
1133 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1134 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1135 return 1;
1136 } else if (ip == ComboAddress("192.0.2.1:53")) {
1137
1138 setLWResult(res, 0, true, false, false);
1139 addRecordToLW(res, domain, QType::CNAME, std::to_string(depth) + "-cname.powerdns.com");
1140 depth++;
1141 return 1;
1142 }
1143
1144 return 0;
1145 });
1146
1147 vector<DNSRecord> ret;
1148 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
f58c8379
RG
1149 BOOST_CHECK_EQUAL(res, RCode::ServFail);
1150 BOOST_CHECK_EQUAL(ret.size(), depth);
4fff116b
RG
1151 /* we have an arbitrary limit at 10 when following a CNAME chain */
1152 BOOST_CHECK_EQUAL(depth, 10 + 2);
1153}
1154
d6e797b8
RG
1155BOOST_AUTO_TEST_CASE(test_time_limit) {
1156 std::unique_ptr<SyncRes> sr;
895449a5 1157 initSR(sr);
d6e797b8
RG
1158
1159 primeHints();
1160
1161 size_t queries = 0;
1162 const DNSName target("cname.powerdns.com.");
1163
1164 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) {
1165
1166 queries++;
1167
1168 if (isRootServer(ip)) {
8455425c 1169 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1170 /* Pretend that this query took 2000 ms */
1171 res->d_usec = 2000;
1172
1173 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1174 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1175 return 1;
1176 } else if (ip == ComboAddress("192.0.2.1:53")) {
1177
1178 setLWResult(res, 0, true, false, false);
1179 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1180 return 1;
1181 }
1182
1183 return 0;
1184 });
1185
1186 /* Set the maximum time to 1 ms */
1187 SyncRes::s_maxtotusec = 1000;
1188
1189 try {
1190 vector<DNSRecord> ret;
1191 sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1192 BOOST_CHECK(false);
1193 }
1194 catch(const ImmediateServFailException& e) {
1195 }
1196 BOOST_CHECK_EQUAL(queries, 1);
1197}
1198
1199BOOST_AUTO_TEST_CASE(test_referral_depth) {
1200 std::unique_ptr<SyncRes> sr;
895449a5 1201 initSR(sr);
d6e797b8
RG
1202
1203 primeHints();
1204
1205 size_t queries = 0;
1206 const DNSName target("www.powerdns.com.");
1207
1208 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) {
1209
1210 queries++;
1211
1212 if (isRootServer(ip)) {
8455425c 1213 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1214
1215 if (domain == DNSName("www.powerdns.com.")) {
1216 addRecordToLW(res, domain, QType::NS, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1217 }
1218 else if (domain == DNSName("ns.powerdns.com.")) {
1219 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
1220 }
1221 else if (domain == DNSName("ns1.powerdns.org.")) {
1222 addRecordToLW(res, domain, QType::NS, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
1223 }
1224 else if (domain == DNSName("ns2.powerdns.org.")) {
1225 addRecordToLW(res, domain, QType::NS, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
1226 }
1227 else if (domain == DNSName("ns3.powerdns.org.")) {
1228 addRecordToLW(res, domain, QType::NS, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
1229 }
1230 else if (domain == DNSName("ns4.powerdns.org.")) {
1231 addRecordToLW(res, domain, QType::NS, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
1232 addRecordToLW(res, domain, QType::A, "192.0.2.1", DNSResourceRecord::AUTHORITY, 172800);
1233 }
1234
1235 return 1;
1236 } else if (ip == ComboAddress("192.0.2.1:53")) {
1237
1238 setLWResult(res, 0, true, false, false);
1239 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1240 return 1;
1241 }
1242
1243 return 0;
1244 });
1245
1246 /* Set the maximum depth low */
1247 SyncRes::s_maxdepth = 10;
1248
1249 try {
1250 vector<DNSRecord> ret;
1251 sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1252 BOOST_CHECK(false);
1253 }
1254 catch(const ImmediateServFailException& e) {
1255 }
1256}
1257
1258BOOST_AUTO_TEST_CASE(test_cname_qperq) {
1259 std::unique_ptr<SyncRes> sr;
895449a5 1260 initSR(sr);
d6e797b8
RG
1261
1262 primeHints();
1263
1264 size_t queries = 0;
1265 const DNSName target("cname.powerdns.com.");
1266
1267 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) {
1268
1269 queries++;
1270
1271 if (isRootServer(ip)) {
1272
8455425c 1273 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1274 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1275 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1276 return 1;
1277 } else if (ip == ComboAddress("192.0.2.1:53")) {
1278
1279 setLWResult(res, 0, true, false, false);
1280 addRecordToLW(res, domain, QType::CNAME, std::to_string(queries) + "-cname.powerdns.com");
1281 return 1;
1282 }
1283
1284 return 0;
1285 });
1286
1287 /* Set the maximum number of questions very low */
1288 SyncRes::s_maxqperq = 5;
1289
1290 try {
1291 vector<DNSRecord> ret;
1292 sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1293 BOOST_CHECK(false);
1294 }
1295 catch(const ImmediateServFailException& e) {
1296 BOOST_CHECK_EQUAL(queries, SyncRes::s_maxqperq);
1297 }
1298}
1299
ccb07d93
RG
1300BOOST_AUTO_TEST_CASE(test_throttled_server) {
1301 std::unique_ptr<SyncRes> sr;
895449a5 1302 initSR(sr);
ccb07d93
RG
1303
1304 primeHints();
1305
1306 const DNSName target("throttled.powerdns.com.");
1307 const ComboAddress ns("192.0.2.1:53");
1308 size_t queriesToNS = 0;
1309
1310 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) {
1311
1312 if (isRootServer(ip)) {
ccb07d93 1313
8455425c 1314 setLWResult(res, 0, false, false, true);
ccb07d93
RG
1315 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1316 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
1317 return 1;
1318 } else if (ip == ns) {
1319
1320 queriesToNS++;
1321
1322 setLWResult(res, 0, true, false, false);
1323 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1324
1325 return 1;
1326 }
1327
1328 return 0;
1329 });
1330
1331 /* mark ns as down */
a712cb56 1332 SyncRes::doThrottle(time(nullptr), ns, SyncRes::s_serverdownthrottletime, 10000);
ccb07d93
RG
1333
1334 vector<DNSRecord> ret;
1335 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
f58c8379
RG
1336 BOOST_CHECK_EQUAL(res, RCode::ServFail);
1337 BOOST_CHECK_EQUAL(ret.size(), 0);
1338 /* we should not have sent any queries to ns */
ccb07d93
RG
1339 BOOST_CHECK_EQUAL(queriesToNS, 0);
1340}
1341
1342BOOST_AUTO_TEST_CASE(test_throttled_server_count) {
1343 std::unique_ptr<SyncRes> sr;
895449a5 1344 initSR(sr);
ccb07d93
RG
1345
1346 primeHints();
1347
1348 const ComboAddress ns("192.0.2.1:53");
1349
1350 const size_t blocks = 10;
1351 /* mark ns as down for 'blocks' queries */
a712cb56 1352 SyncRes::doThrottle(time(nullptr), ns, SyncRes::s_serverdownthrottletime, blocks);
ccb07d93
RG
1353
1354 for (size_t idx = 0; idx < blocks; idx++) {
a712cb56 1355 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns));
ccb07d93
RG
1356 }
1357
1358 /* we have been throttled 'blocks' times, we should not be throttled anymore */
a712cb56 1359 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns));
ccb07d93
RG
1360}
1361
1362BOOST_AUTO_TEST_CASE(test_throttled_server_time) {
1363 std::unique_ptr<SyncRes> sr;
895449a5 1364 initSR(sr);
ccb07d93
RG
1365
1366 primeHints();
1367
1368 const ComboAddress ns("192.0.2.1:53");
1369
1370 const size_t seconds = 1;
1371 /* mark ns as down for 'seconds' seconds */
a712cb56
RG
1372 SyncRes::doThrottle(time(nullptr), ns, seconds, 10000);
1373
1374 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns));
ccb07d93
RG
1375
1376 sleep(seconds + 1);
1377
1378 /* we should not be throttled anymore */
a712cb56 1379 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns));
ccb07d93
RG
1380}
1381
f58c8379
RG
1382BOOST_AUTO_TEST_CASE(test_dont_query_server) {
1383 std::unique_ptr<SyncRes> sr;
895449a5 1384 initSR(sr);
f58c8379
RG
1385
1386 primeHints();
1387
1388 const DNSName target("throttled.powerdns.com.");
1389 const ComboAddress ns("192.0.2.1:53");
1390 size_t queriesToNS = 0;
1391
1392 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) {
1393
1394 if (isRootServer(ip)) {
1395
8455425c 1396 setLWResult(res, 0, false, false, true);
f58c8379
RG
1397 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1398 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
1399 return 1;
1400 } else if (ip == ns) {
1401
1402 queriesToNS++;
1403
1404 setLWResult(res, 0, true, false, false);
1405 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1406
1407 return 1;
1408 }
1409
1410 return 0;
1411 });
1412
1413 /* prevent querying this NS */
9065eb05 1414 SyncRes::addDontQuery(Netmask(ns));
f58c8379
RG
1415
1416 vector<DNSRecord> ret;
1417 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1418 BOOST_CHECK_EQUAL(res, RCode::ServFail);
1419 BOOST_CHECK_EQUAL(ret.size(), 0);
1420 /* we should not have sent any queries to ns */
1421 BOOST_CHECK_EQUAL(queriesToNS, 0);
1422}
1423
1424BOOST_AUTO_TEST_CASE(test_root_nx_trust) {
1425 std::unique_ptr<SyncRes> sr;
895449a5 1426 initSR(sr);
f58c8379
RG
1427
1428 primeHints();
1429
1430 const DNSName target1("powerdns.com.");
1431 const DNSName target2("notpowerdns.com.");
1432 const ComboAddress ns("192.0.2.1:53");
1433 size_t queriesCount = 0;
1434
1435 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) {
1436
1437 queriesCount++;
1438
1439 if (isRootServer(ip)) {
1440
1441 if (domain == target1) {
1442 setLWResult(res, RCode::NXDomain, true, false, true);
1443 addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
1444 }
1445 else {
1446 setLWResult(res, 0, true, false, true);
1447 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1448 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
1449 }
1450
1451 return 1;
1452 } else if (ip == ns) {
1453
1454 setLWResult(res, 0, true, false, false);
1455 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1456
1457 return 1;
1458 }
1459
1460 return 0;
1461 });
1462
1463 vector<DNSRecord> ret;
1464 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
1465 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1466 BOOST_CHECK_EQUAL(ret.size(), 1);
1467 /* one for target1 and one for the entire TLD */
a712cb56 1468 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
f58c8379
RG
1469
1470 ret.clear();
1471 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
1472 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1473 BOOST_CHECK_EQUAL(ret.size(), 1);
1474 /* one for target1 and one for the entire TLD */
a712cb56 1475 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
f58c8379
RG
1476
1477 /* we should have sent only one query */
1478 BOOST_CHECK_EQUAL(queriesCount, 1);
1479}
1480
898856ca
RG
1481BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific) {
1482 std::unique_ptr<SyncRes> sr;
1483 init();
1484 initSR(sr, true, false);
1485
1486 primeHints();
1487
1488 const DNSName target1("powerdns.com.");
1489 const DNSName target2("notpowerdns.com.");
1490 const ComboAddress ns("192.0.2.1:53");
1491 size_t queriesCount = 0;
1492
1493 /* This time the root denies target1 with a "com." SOA instead of a "." one.
1494 We should add target1 to the negcache, but not "com.". */
1495
1496 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) {
1497
1498 queriesCount++;
1499
1500 if (isRootServer(ip)) {
1501
1502 if (domain == target1) {
1503 setLWResult(res, RCode::NXDomain, true, false, true);
1504 addRecordToLW(res, "com.", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
1505 }
1506 else {
1507 setLWResult(res, 0, true, false, true);
1508 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1509 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
1510 }
1511
1512 return 1;
1513 } else if (ip == ns) {
1514
1515 setLWResult(res, 0, true, false, false);
1516 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1517
1518 return 1;
1519 }
1520
1521 return 0;
1522 });
1523
1524 vector<DNSRecord> ret;
1525 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
1526 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1527 BOOST_CHECK_EQUAL(ret.size(), 1);
1528
1529 /* even with root-nx-trust on and a NX answer from the root,
1530 we should not have cached the entire TLD this time. */
a712cb56 1531 BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1);
898856ca
RG
1532
1533 ret.clear();
1534 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
1535 BOOST_CHECK_EQUAL(res, RCode::NoError);
1536 BOOST_REQUIRE_EQUAL(ret.size(), 1);
1537 BOOST_REQUIRE(ret[0].d_type == QType::A);
1538 BOOST_CHECK_EQUAL(ret[0].d_name, target2);
1539 BOOST_CHECK(getRR<ARecordContent>(ret[0])->getCA() == ComboAddress("192.0.2.2"));
1540
a712cb56 1541 BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1);
898856ca
RG
1542
1543 BOOST_CHECK_EQUAL(queriesCount, 3);
1544}
1545
f58c8379
RG
1546BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust) {
1547 std::unique_ptr<SyncRes> sr;
895449a5 1548 initSR(sr);
f58c8379
RG
1549
1550 primeHints();
1551
1552 const DNSName target1("powerdns.com.");
1553 const DNSName target2("notpowerdns.com.");
1554 const ComboAddress ns("192.0.2.1:53");
1555 size_t queriesCount = 0;
1556
1557 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) {
1558
1559 queriesCount++;
1560
1561 if (isRootServer(ip)) {
1562
1563 if (domain == target1) {
1564 setLWResult(res, RCode::NXDomain, true, false, true);
1565 addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
1566 }
1567 else {
1568 setLWResult(res, 0, true, false, true);
1569 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1570 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
1571 }
1572
1573 return 1;
1574 } else if (ip == ns) {
1575
1576 setLWResult(res, 0, true, false, false);
1577 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1578
1579 return 1;
1580 }
1581
1582 return 0;
1583 });
1584
1585 SyncRes::s_rootNXTrust = false;
1586
1587 vector<DNSRecord> ret;
1588 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
1589 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1590 BOOST_CHECK_EQUAL(ret.size(), 1);
1591 /* one for target1 */
a712cb56 1592 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
f58c8379
RG
1593
1594 ret.clear();
1595 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
b7f378d1 1596 BOOST_CHECK_EQUAL(res, RCode::NoError);
f58c8379
RG
1597 BOOST_CHECK_EQUAL(ret.size(), 1);
1598 /* one for target1 */
a712cb56 1599 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
f58c8379
RG
1600
1601 /* we should have sent three queries */
1602 BOOST_CHECK_EQUAL(queriesCount, 3);
1603}
1604
1605BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response) {
1606 std::unique_ptr<SyncRes> sr;
895449a5 1607 initSR(sr);
f58c8379
RG
1608
1609 primeHints();
1610
1611 const DNSName target("www.powerdns.com.");
1612 const DNSName cnameTarget("cname.powerdns.com.");
1613
9065eb05 1614 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
f58c8379
RG
1615
1616 EDNSSubnetOpts incomingECS;
1617 incomingECS.source = Netmask("192.0.2.128/32");
1618 sr->setIncomingECSFound(true);
1619 sr->setIncomingECS(incomingECS);
1620
1621 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) {
1622
1623 BOOST_REQUIRE(srcmask);
1624 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
1625
1626 if (isRootServer(ip)) {
8455425c 1627 setLWResult(res, 0, false, false, true);
f58c8379
RG
1628 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1629 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1630
1631 return 1;
1632 } else if (ip == ComboAddress("192.0.2.1:53")) {
1633 if (domain == target) {
1634 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
1635 setLWResult(res, RCode::NXDomain, true, false, true);
1636 addRecordToLW(res, domain, QType::CNAME, cnameTarget.toString());
1637 addRecordToLW(res, "powerdns.com", QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1638 }
1639 else if (domain == cnameTarget) {
1640 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
1641 but we might if we still chase the CNAME. */
1642 setLWResult(res, RCode::NXDomain, true, false, true);
1643 addRecordToLW(res, "powerdns.com", QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
1644 }
1645
1646 return 1;
1647 }
1648
1649 return 0;
1650 });
1651
1652 vector<DNSRecord> ret;
1653 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1654 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1655 BOOST_CHECK_EQUAL(ret.size(), 2);
1656 /* no negative cache entry because the response was variable */
a712cb56 1657 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0);
f58c8379
RG
1658}
1659
d6e797b8
RG
1660BOOST_AUTO_TEST_CASE(test_ns_speed) {
1661 std::unique_ptr<SyncRes> sr;
895449a5 1662 initSR(sr);
30ee601a 1663
d6e797b8 1664 primeHints();
30ee601a 1665
d6e797b8 1666 const DNSName target("powerdns.com.");
30ee601a 1667
d6e797b8 1668 std::map<ComboAddress, uint64_t> nsCounts;
30ee601a 1669
d6e797b8 1670 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) {
30ee601a 1671
d6e797b8 1672 if (isRootServer(ip)) {
8455425c 1673 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1674 addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1675 addRecordToLW(res, domain, QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1676 addRecordToLW(res, domain, QType::NS, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
30ee601a 1677
d6e797b8
RG
1678 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1679 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600);
1680 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
1681 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 3600);
1682 addRecordToLW(res, "pdns-public-ns3.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 3600);
1683 addRecordToLW(res, "pdns-public-ns3.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 3600);
30ee601a 1684
d6e797b8
RG
1685 return 1;
1686 } else {
1687 nsCounts[ip]++;
30ee601a 1688
d6e797b8
RG
1689 if (ip == ComboAddress("[2001:DB8::2]:53") || ip == ComboAddress("192.0.2.2:53")) {
1690 BOOST_CHECK_LT(nsCounts.size(), 3);
1691
1692 /* let's time out on pdns-public-ns2.powerdns.com. */
1693 return 0;
1694 }
1695 else if (ip == ComboAddress("192.0.2.1:53")) {
1696 BOOST_CHECK_EQUAL(nsCounts.size(), 3);
1697
1698 setLWResult(res, 0, true, false, true);
1699 addRecordToLW(res, domain, QType::A, "192.0.2.254");
1700 return 1;
1701 }
1702
1703 return 0;
1704 }
30ee601a 1705
d6e797b8
RG
1706 return 0;
1707 });
30ee601a 1708
d6e797b8
RG
1709 struct timeval now;
1710 gettimeofday(&now, 0);
30ee601a 1711
d6e797b8
RG
1712 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1713 then pdns-public-ns1.powerdns.com. on IPv4 */
a712cb56
RG
1714 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now);
1715 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now);
1716 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now);
1717 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now);
1718 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now);
1719 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now);
30ee601a 1720
d6e797b8
RG
1721 vector<DNSRecord> ret;
1722 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1723 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
1724 BOOST_CHECK_EQUAL(ret.size(), 1);
1725 BOOST_CHECK_EQUAL(nsCounts.size(), 3);
1726 BOOST_CHECK_EQUAL(nsCounts[ComboAddress("192.0.2.1:53")], 1);
1727 BOOST_CHECK_EQUAL(nsCounts[ComboAddress("192.0.2.2:53")], 1);
1728 BOOST_CHECK_EQUAL(nsCounts[ComboAddress("[2001:DB8::2]:53")], 1);
1729}
30ee601a 1730
d6e797b8
RG
1731BOOST_AUTO_TEST_CASE(test_flawed_nsset) {
1732 std::unique_ptr<SyncRes> sr;
895449a5 1733 initSR(sr);
30ee601a 1734
d6e797b8 1735 primeHints();
30ee601a 1736
d6e797b8 1737 const DNSName target("powerdns.com.");
30ee601a 1738
d6e797b8
RG
1739 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) {
1740
1741 if (isRootServer(ip)) {
8455425c 1742 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1743 addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1744
1745 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1746
1747 return 1;
1748 } else if (ip == ComboAddress("192.0.2.1:53")) {
1749 setLWResult(res, 0, true, false, true);
1750 addRecordToLW(res, domain, QType::A, "192.0.2.254");
1751 return 1;
1752 }
1753
1754 return 0;
1755 });
1756
1757 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1758 time_t now = time(nullptr);
1759 std::vector<DNSRecord> records;
1760 std::vector<shared_ptr<RRSIGRecordContent> > sigs;
1761 addRecordToList(records, target, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, now + 3600);
1762
2b984251 1763 t_RC->replace(now, target, QType(QType::NS), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, boost::optional<Netmask>());
d6e797b8
RG
1764
1765 vector<DNSRecord> ret;
1766 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1767 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
1768 BOOST_CHECK_EQUAL(ret.size(), 1);
1769}
1770
3337c2f7
RG
1771BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset) {
1772 std::unique_ptr<SyncRes> sr;
895449a5 1773 initSR(sr);
3337c2f7
RG
1774
1775 primeHints();
1776
1777 const DNSName target("powerdns.com.");
1778 size_t queriesCount = 0;
1779
1780 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) {
1781
1782 queriesCount++;
1783
1784 if (isRootServer(ip) && domain == target) {
8455425c 1785 setLWResult(res, 0, false, false, true);
3337c2f7
RG
1786 addRecordToLW(res, domain, QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1787 addRecordToLW(res, domain, QType::NS, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1788 return 1;
1789 } else if (domain == DNSName("pdns-public-ns2.powerdns.com.") || domain == DNSName("pdns-public-ns3.powerdns.com.")){
1790 setLWResult(res, 0, true, false, true);
1791 addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
1792 return 1;
1793 }
1794
1795 return 0;
1796 });
1797
1798 vector<DNSRecord> ret;
1799 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1800 BOOST_CHECK_EQUAL(res, RCode::ServFail);
1801 BOOST_CHECK_EQUAL(ret.size(), 0);
1802 /* one query to get NSs, then A and AAAA for each NS */
1803 BOOST_CHECK_EQUAL(queriesCount, 5);
1804}
1805
d6e797b8
RG
1806BOOST_AUTO_TEST_CASE(test_cache_hit) {
1807 std::unique_ptr<SyncRes> sr;
895449a5 1808 initSR(sr);
d6e797b8
RG
1809
1810 primeHints();
1811
1812 const DNSName target("powerdns.com.");
1813
1814 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) {
1815
1816 return 0;
1817 });
1818
1819 /* we populate the cache with eveything we need */
1820 time_t now = time(nullptr);
1821 std::vector<DNSRecord> records;
1822 std::vector<shared_ptr<RRSIGRecordContent> > sigs;
1823
1824 addRecordToList(records, target, QType::A, "192.0.2.1", DNSResourceRecord::ANSWER, now + 3600);
2b984251 1825 t_RC->replace(now, target , QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, boost::optional<Netmask>());
d6e797b8
RG
1826
1827 vector<DNSRecord> ret;
1828 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1829 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
1830 BOOST_CHECK_EQUAL(ret.size(), 1);
1831}
1832
648bcbd1
RG
1833BOOST_AUTO_TEST_CASE(test_no_rd) {
1834 std::unique_ptr<SyncRes> sr;
895449a5 1835 initSR(sr);
648bcbd1
RG
1836
1837 primeHints();
1838
1839 const DNSName target("powerdns.com.");
1840 size_t queriesCount = 0;
1841
1842 sr->setCacheOnly();
1843
1844 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) {
1845
1846 queriesCount++;
1847 return 0;
1848 });
1849
1850 vector<DNSRecord> ret;
1851 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1852 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
1853 BOOST_CHECK_EQUAL(ret.size(), 0);
1854 BOOST_CHECK_EQUAL(queriesCount, 0);
1855}
1856
d6e797b8
RG
1857BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl) {
1858 std::unique_ptr<SyncRes> sr;
a53e8fe3 1859 const time_t now = time(nullptr);
895449a5 1860 initSR(sr);
d6e797b8
RG
1861
1862 primeHints();
1863
1864 const DNSName target("cachettl.powerdns.com.");
1865 const ComboAddress ns("192.0.2.1:53");
1866
1867 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) {
1868
1869 if (isRootServer(ip)) {
1870
8455425c 1871 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1872 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1873 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 7200);
1874 return 1;
1875 } else if (ip == ns) {
1876
1877 setLWResult(res, 0, true, false, false);
1878 addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, 10);
1879
1880 return 1;
1881 }
1882
1883 return 0;
1884 });
1885
1886 SyncRes::s_minimumTTL = 60;
1887 SyncRes::s_maxcachettl = 3600;
1888
1889 vector<DNSRecord> ret;
1890 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1891 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
1892 BOOST_REQUIRE_EQUAL(ret.size(), 1);
1893 BOOST_CHECK_EQUAL(ret[0].d_ttl, SyncRes::s_minimumTTL);
1894
1895 const ComboAddress who;
1896 vector<DNSRecord> cached;
24bb9b58 1897 BOOST_REQUIRE_GT(t_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
d6e797b8
RG
1898 BOOST_REQUIRE_EQUAL(cached.size(), 1);
1899 BOOST_REQUIRE_GT(cached[0].d_ttl, now);
1900 BOOST_CHECK_EQUAL((cached[0].d_ttl - now), SyncRes::s_minimumTTL);
1901
1902 cached.clear();
24bb9b58 1903 BOOST_REQUIRE_GT(t_RC->get(now, target, QType(QType::NS), false, &cached, who), 0);
d6e797b8
RG
1904 BOOST_REQUIRE_EQUAL(cached.size(), 1);
1905 BOOST_REQUIRE_GT(cached[0].d_ttl, now);
1906 BOOST_CHECK_LE((cached[0].d_ttl - now), SyncRes::s_maxcachettl);
1907}
1908
1909BOOST_AUTO_TEST_CASE(test_cache_expired_ttl) {
1910 std::unique_ptr<SyncRes> sr;
895449a5 1911 initSR(sr);
d6e797b8
RG
1912
1913 primeHints();
1914
1915 const DNSName target("powerdns.com.");
1916
1917 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) {
1918
1919 if (isRootServer(ip)) {
8455425c 1920 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1921 addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1922
1923 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1924
1925 return 1;
1926 } else if (ip == ComboAddress("192.0.2.1:53")) {
1927 setLWResult(res, 0, true, false, true);
1928 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1929 return 1;
1930 }
1931
1932 return 0;
1933 });
1934
1935 /* we populate the cache with entries that expired 60s ago*/
1936 time_t now = time(nullptr);
1937 std::vector<DNSRecord> records;
1938 std::vector<shared_ptr<RRSIGRecordContent> > sigs;
1939 addRecordToList(records, target, QType::A, "192.0.2.42", DNSResourceRecord::ANSWER, now - 60);
1940
2b984251 1941 t_RC->replace(now - 3600, target, QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, boost::optional<Netmask>());
d6e797b8
RG
1942
1943 vector<DNSRecord> ret;
1944 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 1945 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
1946 BOOST_REQUIRE_EQUAL(ret.size(), 1);
1947 BOOST_REQUIRE(ret[0].d_type == QType::A);
1948 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
1949}
1950
1951BOOST_AUTO_TEST_CASE(test_delegation_only) {
1952 std::unique_ptr<SyncRes> sr;
895449a5 1953 initSR(sr);
d6e797b8
RG
1954
1955 primeHints();
1956
1957 /* Thanks, Verisign */
9065eb05
RG
1958 SyncRes::addDelegationOnly(DNSName("com."));
1959 SyncRes::addDelegationOnly(DNSName("net."));
d6e797b8
RG
1960
1961 const DNSName target("nx-powerdns.com.");
1962
1963 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) {
1964
1965 if (isRootServer(ip)) {
8455425c 1966 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1967 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1968 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1969 return 1;
1970 } else if (ip == ComboAddress("192.0.2.1:53")) {
1971
1972 setLWResult(res, 0, true, false, true);
1973 addRecordToLW(res, domain, QType::A, "192.0.2.42");
1974 return 1;
1975 }
1976
1977 return 0;
1978 });
1979
1980 vector<DNSRecord> ret;
1981 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1982 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
1983 BOOST_CHECK_EQUAL(ret.size(), 0);
1984}
1985
1986BOOST_AUTO_TEST_CASE(test_unauth_any) {
1987 std::unique_ptr<SyncRes> sr;
895449a5 1988 initSR(sr);
d6e797b8
RG
1989
1990 primeHints();
1991
1992 const DNSName target("powerdns.com.");
1993
1994 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) {
1995
1996 if (isRootServer(ip)) {
8455425c 1997 setLWResult(res, 0, false, false, true);
d6e797b8
RG
1998 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1999 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
2000 return 1;
2001 } else if (ip == ComboAddress("192.0.2.1:53")) {
2002
2003 setLWResult(res, 0, false, false, true);
2004 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2005 return 1;
2006 }
2007
2008 return 0;
2009 });
2010
2011 vector<DNSRecord> ret;
2012 int res = sr->beginResolve(target, QType(QType::ANY), QClass::IN, ret);
2013 BOOST_CHECK_EQUAL(res, RCode::ServFail);
2014 BOOST_CHECK_EQUAL(ret.size(), 0);
2015}
2016
2017BOOST_AUTO_TEST_CASE(test_no_data) {
2018 std::unique_ptr<SyncRes> sr;
895449a5 2019 initSR(sr);
d6e797b8
RG
2020
2021 primeHints();
2022
2023 const DNSName target("powerdns.com.");
2024
2025 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) {
2026
2027 setLWResult(res, 0, true, false, true);
2028 return 1;
2029 });
2030
2031 vector<DNSRecord> ret;
2032 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2033 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
2034 BOOST_CHECK_EQUAL(ret.size(), 0);
2035}
2036
2037BOOST_AUTO_TEST_CASE(test_skip_opt_any) {
2038 std::unique_ptr<SyncRes> sr;
895449a5 2039 initSR(sr);
d6e797b8
RG
2040
2041 primeHints();
2042
2043 const DNSName target("powerdns.com.");
2044
2045 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) {
2046
2047 setLWResult(res, 0, true, false, true);
2048 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2049 addRecordToLW(res, domain, QType::ANY, "0 0");
2050 addRecordToLW(res, domain, QType::OPT, "");
2051 return 1;
2052 });
2053
2054 vector<DNSRecord> ret;
2055 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2056 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
2057 BOOST_CHECK_EQUAL(ret.size(), 1);
2058}
2059
2060BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec) {
2061 std::unique_ptr<SyncRes> sr;
895449a5 2062 initSR(sr);
d6e797b8
RG
2063
2064 primeHints();
2065
2066 const DNSName target("powerdns.com.");
2067
2068 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) {
2069
2070 setLWResult(res, 0, true, false, true);
2071 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
2072 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2073 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
2b984251 2074 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
d6e797b8
RG
2075 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
2076 return 1;
2077 });
2078
2079 vector<DNSRecord> ret;
2080 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2081 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
2082 BOOST_CHECK_EQUAL(ret.size(), 1);
2083}
2084
2085BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec) {
2086 std::unique_ptr<SyncRes> sr;
895449a5 2087 initSR(sr, true);
d6e797b8
RG
2088
2089 primeHints();
2090
2091 const DNSName target("powerdns.com.");
2092
2093 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) {
2094
2095 setLWResult(res, 0, true, false, true);
2096 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
2097 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2098 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
2b984251 2099 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
d6e797b8
RG
2100 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
2101 return 1;
2102 });
2103
2104 vector<DNSRecord> ret;
2105 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2106 BOOST_CHECK_EQUAL(res, RCode::NoError);
d6e797b8
RG
2107 BOOST_CHECK_EQUAL(ret.size(), 4);
2108}
2109
2110BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec) {
2111 std::unique_ptr<SyncRes> sr;
895449a5 2112 initSR(sr);
d6e797b8
RG
2113
2114 primeHints();
2115
2116 const DNSName target("powerdns.com.");
2117
2118 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) {
2119
2120 setLWResult(res, RCode::NXDomain, true, false, true);
2121 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
2122 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2123 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
2b984251 2124 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
d6e797b8
RG
2125 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
2126 return 1;
2127 });
2128
2129 vector<DNSRecord> ret;
2130 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2131 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
2132 BOOST_CHECK_EQUAL(ret.size(), 1);
2133}
2134
2135BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec) {
2136 std::unique_ptr<SyncRes> sr;
895449a5 2137 initSR(sr, true);
d6e797b8
RG
2138
2139 primeHints();
2140
2141 const DNSName target("powerdns.com.");
2142
2143 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) {
2144
2145 setLWResult(res, RCode::NXDomain, true, false, true);
2146 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
2147 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
2148 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
2b984251 2149 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
d6e797b8
RG
2150 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
2151 return 1;
2152 });
2153
2154 vector<DNSRecord> ret;
2155 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2156 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
2157 BOOST_CHECK_EQUAL(ret.size(), 4);
2158}
2159
648bcbd1
RG
2160BOOST_AUTO_TEST_CASE(test_qclass_none) {
2161 std::unique_ptr<SyncRes> sr;
895449a5 2162 initSR(sr);
648bcbd1
RG
2163
2164 primeHints();
2165
2166 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
2167 size_t queriesCount = 0;
2168
2169 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) {
2170
2171 queriesCount++;
2172 return 0;
2173 });
2174
2175 const DNSName target("powerdns.com.");
2176 vector<DNSRecord> ret;
2177 int res = sr->beginResolve(target, QType(QType::A), QClass::NONE, ret);
2178 BOOST_CHECK_EQUAL(res, -1);
2179 BOOST_CHECK_EQUAL(ret.size(), 0);
2180 BOOST_CHECK_EQUAL(queriesCount, 0);
2181}
2182
2183BOOST_AUTO_TEST_CASE(test_xfr) {
2184 std::unique_ptr<SyncRes> sr;
895449a5 2185 initSR(sr);
648bcbd1
RG
2186
2187 primeHints();
2188
2189 /* {A,I}XFR should be rejected right away */
2190 size_t queriesCount = 0;
2191
2192 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) {
2193
2194 cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
2195 queriesCount++;
2196 return 0;
2197 });
2198
2199 const DNSName target("powerdns.com.");
2200 vector<DNSRecord> ret;
2201 int res = sr->beginResolve(target, QType(QType::AXFR), QClass::IN, ret);
2202 BOOST_CHECK_EQUAL(res, -1);
2203 BOOST_CHECK_EQUAL(ret.size(), 0);
2204 BOOST_CHECK_EQUAL(queriesCount, 0);
2205
2206 res = sr->beginResolve(target, QType(QType::IXFR), QClass::IN, ret);
2207 BOOST_CHECK_EQUAL(res, -1);
2208 BOOST_CHECK_EQUAL(ret.size(), 0);
2209 BOOST_CHECK_EQUAL(queriesCount, 0);
2210}
2211
2212BOOST_AUTO_TEST_CASE(test_special_names) {
2213 std::unique_ptr<SyncRes> sr;
895449a5 2214 initSR(sr);
648bcbd1
RG
2215
2216 primeHints();
2217
2218 /* special names should be handled internally */
2219
2220 size_t queriesCount = 0;
2221
2222 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) {
2223
2224 queriesCount++;
2225 return 0;
2226 });
2227
2228 vector<DNSRecord> ret;
2229 int res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR), QClass::IN, ret);
b7f378d1 2230 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2231 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2232 BOOST_CHECK(ret[0].d_type == QType::PTR);
2233 BOOST_CHECK_EQUAL(queriesCount, 0);
2234
2235 ret.clear();
2236 res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY), QClass::IN, ret);
b7f378d1 2237 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2238 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2239 BOOST_CHECK(ret[0].d_type == QType::PTR);
2240 BOOST_CHECK_EQUAL(queriesCount, 0);
2241
2242 ret.clear();
2243 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);
b7f378d1 2244 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2245 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2246 BOOST_CHECK(ret[0].d_type == QType::PTR);
2247 BOOST_CHECK_EQUAL(queriesCount, 0);
2248
2249 ret.clear();
2250 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);
b7f378d1 2251 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2252 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2253 BOOST_CHECK(ret[0].d_type == QType::PTR);
2254 BOOST_CHECK_EQUAL(queriesCount, 0);
2255
2256 ret.clear();
2257 res = sr->beginResolve(DNSName("localhost."), QType(QType::A), QClass::IN, ret);
b7f378d1 2258 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2259 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2260 BOOST_CHECK(ret[0].d_type == QType::A);
2261 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), "127.0.0.1");
2262 BOOST_CHECK_EQUAL(queriesCount, 0);
2263
2264 ret.clear();
2265 res = sr->beginResolve(DNSName("localhost."), QType(QType::AAAA), QClass::IN, ret);
b7f378d1 2266 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2267 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2268 BOOST_CHECK(ret[0].d_type == QType::AAAA);
2269 BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(ret[0])->getCA().toString(), "::1");
2270 BOOST_CHECK_EQUAL(queriesCount, 0);
2271
2272 ret.clear();
2273 res = sr->beginResolve(DNSName("localhost."), QType(QType::ANY), QClass::IN, ret);
b7f378d1 2274 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2275 BOOST_REQUIRE_EQUAL(ret.size(), 2);
2276 for (const auto& rec : ret) {
2277 BOOST_REQUIRE((rec.d_type == QType::A) || rec.d_type == QType::AAAA);
2278 if (rec.d_type == QType::A) {
2279 BOOST_CHECK_EQUAL(getRR<ARecordContent>(rec)->getCA().toString(), "127.0.0.1");
2280 }
2281 else {
2282 BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(rec)->getCA().toString(), "::1");
2283 }
2284 }
2285 BOOST_CHECK_EQUAL(queriesCount, 0);
2286
2287 ret.clear();
2288 res = sr->beginResolve(DNSName("version.bind."), QType(QType::TXT), QClass::CHAOS, ret);
b7f378d1 2289 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2290 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2291 BOOST_CHECK(ret[0].d_type == QType::TXT);
2292 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
2293 BOOST_CHECK_EQUAL(queriesCount, 0);
2294
2295 ret.clear();
2296 res = sr->beginResolve(DNSName("version.bind."), QType(QType::ANY), QClass::CHAOS, ret);
b7f378d1 2297 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2298 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2299 BOOST_CHECK(ret[0].d_type == QType::TXT);
2300 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
2301 BOOST_CHECK_EQUAL(queriesCount, 0);
2302
2303 ret.clear();
2304 res = sr->beginResolve(DNSName("version.pdns."), QType(QType::TXT), QClass::CHAOS, ret);
b7f378d1 2305 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2306 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2307 BOOST_CHECK(ret[0].d_type == QType::TXT);
2308 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
2309 BOOST_CHECK_EQUAL(queriesCount, 0);
2310
2311 ret.clear();
2312 res = sr->beginResolve(DNSName("version.pdns."), QType(QType::ANY), QClass::CHAOS, ret);
b7f378d1 2313 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2314 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2315 BOOST_CHECK(ret[0].d_type == QType::TXT);
2316 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
2317 BOOST_CHECK_EQUAL(queriesCount, 0);
2318
2319 ret.clear();
2320 res = sr->beginResolve(DNSName("id.server."), QType(QType::TXT), QClass::CHAOS, ret);
b7f378d1 2321 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2322 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2323 BOOST_CHECK(ret[0].d_type == QType::TXT);
2324 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\"");
2325 BOOST_CHECK_EQUAL(queriesCount, 0);
2326
2327 ret.clear();
2328 res = sr->beginResolve(DNSName("id.server."), QType(QType::ANY), QClass::CHAOS, ret);
b7f378d1 2329 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2330 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2331 BOOST_CHECK(ret[0].d_type == QType::TXT);
2332 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\"");
2333 BOOST_CHECK_EQUAL(queriesCount, 0);
2334}
2335
2336BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz) {
2337 std::unique_ptr<SyncRes> sr;
895449a5 2338 initSR(sr);
648bcbd1
RG
2339
2340 primeHints();
2341
2342 const DNSName target("rpz.powerdns.com.");
2343 const ComboAddress ns("192.0.2.1:53");
2344
2345 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) {
2346
2347 if (isRootServer(ip)) {
8455425c 2348 setLWResult(res, false, true, false, true);
648bcbd1
RG
2349 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
2350 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
2351 return 1;
2352 } else if (ip == ns) {
2353
2354 setLWResult(res, 0, true, false, true);
2355 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2356 return 1;
2357 }
2358
2359 return 0;
2360 });
2361
2362 DNSFilterEngine::Policy pol;
2363 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
6b972d59
RG
2364 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
2365 zone->setName("Unit test policy 0");
2366 zone->addNSIPTrigger(Netmask(ns, 32), pol);
648bcbd1 2367 auto luaconfsCopy = g_luaconfs.getCopy();
6b972d59 2368 luaconfsCopy.dfe.addZone(zone);
648bcbd1
RG
2369 g_luaconfs.setState(luaconfsCopy);
2370
2371 vector<DNSRecord> ret;
2372 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2373 BOOST_CHECK_EQUAL(res, -2);
2374 BOOST_CHECK_EQUAL(ret.size(), 0);
2375}
2376
2377BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz) {
2378 std::unique_ptr<SyncRes> sr;
895449a5 2379 initSR(sr);
648bcbd1
RG
2380
2381 primeHints();
2382
2383 const DNSName target("rpz.powerdns.com.");
2384 const ComboAddress ns("[2001:DB8::42]:53");
2385
2386 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) {
2387
2388 if (isRootServer(ip)) {
8455425c 2389 setLWResult(res, 0, false, false, true);
648bcbd1
RG
2390 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
2391 addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
2392 return 1;
2393 } else if (ip == ns) {
2394
2395 setLWResult(res, 0, true, false, true);
2396 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2397 return 1;
2398 }
2399
2400 return 0;
2401 });
2402
2403 DNSFilterEngine::Policy pol;
2404 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
6b972d59
RG
2405 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
2406 zone->setName("Unit test policy 0");
2407 zone->addNSIPTrigger(Netmask(ns, 128), pol);
648bcbd1 2408 auto luaconfsCopy = g_luaconfs.getCopy();
6b972d59 2409 luaconfsCopy.dfe.addZone(zone);
648bcbd1
RG
2410 g_luaconfs.setState(luaconfsCopy);
2411
2412 vector<DNSRecord> ret;
2413 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2414 BOOST_CHECK_EQUAL(res, -2);
2415 BOOST_CHECK_EQUAL(ret.size(), 0);
2416}
2417
2418BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz) {
2419 std::unique_ptr<SyncRes> sr;
895449a5 2420 initSR(sr);
648bcbd1
RG
2421
2422 primeHints();
2423
2424 const DNSName target("rpz.powerdns.com.");
2425 const ComboAddress ns("192.0.2.1:53");
2426 const DNSName nsName("ns1.powerdns.com.");
2427
2428 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) {
2429
2430 if (isRootServer(ip)) {
8455425c 2431 setLWResult(res, 0, false, false, true);
648bcbd1
RG
2432 addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800);
2433 addRecordToLW(res, nsName, QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
2434 return 1;
2435 } else if (ip == ns) {
2436
2437 setLWResult(res, 0, true, false, true);
2438 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2439 return 1;
2440 }
2441
2442 return 0;
2443 });
2444
2445 DNSFilterEngine::Policy pol;
2446 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
6b972d59
RG
2447 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
2448 zone->setName("Unit test policy 0");
2449 zone->addNSTrigger(nsName, pol);
648bcbd1 2450 auto luaconfsCopy = g_luaconfs.getCopy();
6b972d59 2451 luaconfsCopy.dfe.addZone(zone);
648bcbd1
RG
2452 g_luaconfs.setState(luaconfsCopy);
2453
2454 vector<DNSRecord> ret;
2455 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2456 BOOST_CHECK_EQUAL(res, -2);
2457 BOOST_CHECK_EQUAL(ret.size(), 0);
2458}
2459
2460BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled) {
2461 std::unique_ptr<SyncRes> sr;
895449a5 2462 initSR(sr);
648bcbd1
RG
2463
2464 primeHints();
2465
2466 const DNSName target("rpz.powerdns.com.");
2467 const ComboAddress ns("192.0.2.1:53");
2468 const DNSName nsName("ns1.powerdns.com.");
2469
2470 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) {
2471
2472 if (isRootServer(ip)) {
8455425c 2473 setLWResult(res, 0, false, false, true);
648bcbd1
RG
2474 addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800);
2475 addRecordToLW(res, nsName, QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
2476 return 1;
2477 } else if (ip == ns) {
2478
2479 setLWResult(res, 0, true, false, true);
2480 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2481 return 1;
2482 }
2483
2484 return 0;
2485 });
2486
2487 DNSFilterEngine::Policy pol;
2488 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
6b972d59
RG
2489 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
2490 zone->setName("Unit test policy 0");
2491 zone->addNSIPTrigger(Netmask(ns, 128), pol);
2492 zone->addNSTrigger(nsName, pol);
648bcbd1 2493 auto luaconfsCopy = g_luaconfs.getCopy();
6b972d59 2494 luaconfsCopy.dfe.addZone(zone);
648bcbd1
RG
2495 g_luaconfs.setState(luaconfsCopy);
2496
2497 /* RPZ is disabled for this query, we should not be blocked */
2498 sr->setWantsRPZ(false);
2499
2500 vector<DNSRecord> ret;
2501 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2502 BOOST_CHECK_EQUAL(res, RCode::NoError);
648bcbd1
RG
2503 BOOST_CHECK_EQUAL(ret.size(), 1);
2504}
2505
3e59ff53
RG
2506BOOST_AUTO_TEST_CASE(test_forward_zone_nord) {
2507 std::unique_ptr<SyncRes> sr;
895449a5 2508 initSR(sr);
3e59ff53
RG
2509
2510 primeHints();
2511
2512 const DNSName target("powerdns.com.");
2513 const ComboAddress ns("192.0.2.1:53");
2514 const ComboAddress forwardedNS("192.0.2.42:53");
2515
2516 SyncRes::AuthDomain ad;
2517 ad.d_rdForward = false;
2518 ad.d_servers.push_back(forwardedNS);
a712cb56 2519 (*SyncRes::t_sstorage.domainmap)[target] = ad;
3e59ff53
RG
2520
2521 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) {
2522
2523 if (ip == forwardedNS) {
6dfff36f
RG
2524 BOOST_CHECK_EQUAL(sendRDQuery, false);
2525
3e59ff53
RG
2526 setLWResult(res, 0, true, false, true);
2527 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2528 return 1;
2529 }
2530
2531 return 0;
2532 });
2533
2534 /* simulate a no-RD query */
2535 sr->setCacheOnly();
2536
2537 vector<DNSRecord> ret;
2538 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2539 BOOST_CHECK_EQUAL(res, RCode::NoError);
3e59ff53
RG
2540 BOOST_CHECK_EQUAL(ret.size(), 1);
2541}
2542
2543BOOST_AUTO_TEST_CASE(test_forward_zone_rd) {
2544 std::unique_ptr<SyncRes> sr;
895449a5 2545 initSR(sr);
3e59ff53
RG
2546
2547 primeHints();
2548
2549 const DNSName target("powerdns.com.");
2550 const ComboAddress ns("192.0.2.1:53");
2551 const ComboAddress forwardedNS("192.0.2.42:53");
2552
2553 SyncRes::AuthDomain ad;
2554 ad.d_rdForward = false;
2555 ad.d_servers.push_back(forwardedNS);
a712cb56 2556 (*SyncRes::t_sstorage.domainmap)[target] = ad;
3e59ff53
RG
2557
2558 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) {
2559
2560 if (ip == forwardedNS) {
6dfff36f
RG
2561 BOOST_CHECK_EQUAL(sendRDQuery, false);
2562
3e59ff53
RG
2563 setLWResult(res, 0, true, false, true);
2564 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2565 return 1;
2566 }
2567
2568 return 0;
2569 });
2570
2571 vector<DNSRecord> ret;
2572 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2573 BOOST_CHECK_EQUAL(res, RCode::NoError);
3e59ff53
RG
2574 BOOST_CHECK_EQUAL(ret.size(), 1);
2575}
2576
2577BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord) {
2578 std::unique_ptr<SyncRes> sr;
895449a5 2579 initSR(sr);
3e59ff53
RG
2580
2581 primeHints();
2582
2583 const DNSName target("powerdns.com.");
2584 const ComboAddress ns("192.0.2.1:53");
2585 const ComboAddress forwardedNS("192.0.2.42:53");
2586
2587 SyncRes::AuthDomain ad;
2588 ad.d_rdForward = true;
2589 ad.d_servers.push_back(forwardedNS);
a712cb56 2590 (*SyncRes::t_sstorage.domainmap)[target] = ad;
3e59ff53
RG
2591
2592 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) {
2593
2594 if (ip == forwardedNS) {
6dfff36f
RG
2595 BOOST_CHECK_EQUAL(sendRDQuery, false);
2596
3e59ff53
RG
2597 setLWResult(res, 0, true, false, true);
2598 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2599 return 1;
2600 }
2601
2602 return 0;
2603 });
2604
2605 /* simulate a no-RD query */
2606 sr->setCacheOnly();
2607
2608 vector<DNSRecord> ret;
2609 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2610 BOOST_CHECK_EQUAL(res, RCode::NoError);
3e59ff53
RG
2611 BOOST_CHECK_EQUAL(ret.size(), 1);
2612}
2613
2614BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd) {
2615 std::unique_ptr<SyncRes> sr;
895449a5 2616 initSR(sr);
3e59ff53
RG
2617
2618 primeHints();
2619
2620 const DNSName target("powerdns.com.");
2621 const ComboAddress ns("192.0.2.1:53");
2622 const ComboAddress forwardedNS("192.0.2.42:53");
2623
2624 SyncRes::AuthDomain ad;
2625 ad.d_rdForward = true;
2626 ad.d_servers.push_back(forwardedNS);
a712cb56 2627 (*SyncRes::t_sstorage.domainmap)[target] = ad;
3e59ff53
RG
2628
2629 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) {
2630
2631 if (ip == forwardedNS) {
6dfff36f
RG
2632 BOOST_CHECK_EQUAL(sendRDQuery, true);
2633
3e59ff53
RG
2634 setLWResult(res, 0, true, false, true);
2635 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2636 return 1;
2637 }
2638
2639 return 0;
2640 });
2641
2642 vector<DNSRecord> ret;
2643 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2644 BOOST_CHECK_EQUAL(res, RCode::NoError);
3e59ff53
RG
2645 BOOST_CHECK_EQUAL(ret.size(), 1);
2646}
2647
f79a4e30
RG
2648BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_oob) {
2649 std::unique_ptr<SyncRes> sr;
2650 init();
2651 initSR(sr, true, false);
2652
2653 primeHints();
2654
2655 size_t queriesCount = 0;
2656 const DNSName target("test.xx.");
2657 const ComboAddress targetAddr("127.0.0.1");
2658 const DNSName ns("localhost.");
2659 const ComboAddress nsAddr("127.0.0.1");
2660 const DNSName authZone("test.xx");
2661
2662 SyncRes::AuthDomain ad;
2663 DNSRecord dr;
2664 dr.d_place = DNSResourceRecord::ANSWER;
2665 dr.d_name = authZone;
2666 dr.d_type = QType::NS;
2667 dr.d_ttl = 1800;
2668 dr.d_content = std::make_shared<NSRecordContent>("localhost.");
2669 ad.d_records.insert(dr);
2670
2671 dr.d_place = DNSResourceRecord::ANSWER;
2672 dr.d_name = authZone;
2673 dr.d_type = QType::A;
2674 dr.d_ttl = 1800;
2675 dr.d_content = std::make_shared<ARecordContent>(nsAddr);
2676 ad.d_records.insert(dr);
2677
a712cb56 2678 (*SyncRes::t_sstorage.domainmap)[authZone] = ad;
f79a4e30
RG
2679
2680 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) {
2681 queriesCount++;
2682 return 0;
2683 });
2684
2685 vector<DNSRecord> ret;
2686 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2687 BOOST_CHECK_EQUAL(res, 0);
2688 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2689 BOOST_CHECK(ret[0].d_type == QType::A);
2690 BOOST_CHECK_EQUAL(queriesCount, 0);
2691 BOOST_CHECK(sr->wasOutOfBand());
2692
2693 /* a second time, to check that the OOB flag is set when the query cache is used */
2694 ret.clear();
2695 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2696 BOOST_CHECK_EQUAL(res, 0);
2697 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2698 BOOST_CHECK(ret[0].d_type == QType::A);
2699 BOOST_CHECK_EQUAL(queriesCount, 0);
2700 BOOST_CHECK(sr->wasOutOfBand());
2701}
2702
3337c2f7
RG
2703BOOST_AUTO_TEST_CASE(test_auth_zone) {
2704 std::unique_ptr<SyncRes> sr;
895449a5 2705 initSR(sr);
3337c2f7
RG
2706
2707 primeHints();
2708
2709 size_t queriesCount = 0;
2710 const DNSName target("powerdns.com.");
2711 const ComboAddress addr("192.0.2.5");
2712
2713 SyncRes::AuthDomain ad;
2714 ad.d_name = target;
2715 DNSRecord dr;
2716 dr.d_place = DNSResourceRecord::ANSWER;
2717 dr.d_name = target;
2718 dr.d_type = QType::SOA;
2719 dr.d_ttl = 3600;
2720 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2721 ad.d_records.insert(dr);
2722
2723 dr.d_place = DNSResourceRecord::ANSWER;
2724 dr.d_name = target;
2725 dr.d_type = QType::A;
2726 dr.d_ttl = 3600;
2727 dr.d_content = std::make_shared<ARecordContent>(addr);
2728 ad.d_records.insert(dr);
2729
2730 auto map = std::make_shared<SyncRes::domainmap_t>();
2731 (*map)[target] = ad;
2732 SyncRes::setDomainMap(map);
2733
2734 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) {
2735
2736 queriesCount++;
2737 setLWResult(res, 0, true, false, true);
2738 addRecordToLW(res, domain, QType::A, "192.0.2.42");
2739 return 1;
2740 });
2741
2742 vector<DNSRecord> ret;
2743 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2744 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
2745 BOOST_CHECK_EQUAL(ret.size(), 1);
2746 BOOST_CHECK(ret[0].d_type == QType::A);
2747 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
2748 BOOST_CHECK_EQUAL(queriesCount, 0);
2749}
2750
2751BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob) {
2752 std::unique_ptr<SyncRes> sr;
895449a5 2753 initSR(sr);
3337c2f7
RG
2754
2755 primeHints();
2756
2757 size_t queriesCount = 0;
2758 const DNSName target("powerdns.com.");
2759 const DNSName authZone("internal.powerdns.com.");
2760 const ComboAddress addr("192.0.2.5");
2761
2762 SyncRes::AuthDomain ad;
2763 ad.d_name = authZone;
2764 DNSRecord dr;
2765 dr.d_place = DNSResourceRecord::ANSWER;
2766 dr.d_name = authZone;
2767 dr.d_type = QType::SOA;
2768 dr.d_ttl = 3600;
2769 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2770 ad.d_records.insert(dr);
2771
2772 dr.d_place = DNSResourceRecord::ANSWER;
2773 dr.d_name = authZone;
2774 dr.d_type = QType::A;
2775 dr.d_ttl = 3600;
2776 dr.d_content = std::make_shared<ARecordContent>(addr);
2777 ad.d_records.insert(dr);
2778
2779 auto map = std::make_shared<SyncRes::domainmap_t>();
2780 (*map)[authZone] = ad;
2781 SyncRes::setDomainMap(map);
2782
2783 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) {
2784
2785 queriesCount++;
2786
2787 if (domain == target) {
2788 setLWResult(res, 0, true, false, true);
2789 addRecordToLW(res, target, QType::CNAME, authZone.toString(), DNSResourceRecord::ANSWER, 3600);
2790 return 1;
2791 }
2792
2793 return 0;
2794 });
2795
2796 vector<DNSRecord> ret;
2797 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2798 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
2799 BOOST_CHECK_EQUAL(ret.size(), 2);
2800 BOOST_CHECK(ret[0].d_type == QType::CNAME);
2801 BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), authZone.toString());
2802 BOOST_CHECK(ret[1].d_type == QType::A);
2803 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[1])->getCA().toString(), addr.toString());
2804 BOOST_CHECK_EQUAL(queriesCount, 1);
2805}
2806
2807BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb) {
2808 std::unique_ptr<SyncRes> sr;
895449a5 2809 initSR(sr);
3337c2f7
RG
2810
2811 primeHints();
2812
2813 size_t queriesCount = 0;
2814 const DNSName target("powerdns.com.");
2815 const DNSName externalCNAME("www.open-xchange.com.");
2816 const ComboAddress addr("192.0.2.5");
2817
2818 SyncRes::AuthDomain ad;
2819 ad.d_name = target;
2820 DNSRecord dr;
2821 dr.d_place = DNSResourceRecord::ANSWER;
2822 dr.d_name = target;
2823 dr.d_type = QType::SOA;
2824 dr.d_ttl = 3600;
2825 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2826 ad.d_records.insert(dr);
2827
2828 dr.d_place = DNSResourceRecord::ANSWER;
2829 dr.d_name = target;
2830 dr.d_type = QType::CNAME;
2831 dr.d_ttl = 3600;
2832 dr.d_content = std::make_shared<CNAMERecordContent>(externalCNAME);
2833 ad.d_records.insert(dr);
2834
2835 auto map = std::make_shared<SyncRes::domainmap_t>();
2836 (*map)[target] = ad;
2837 SyncRes::setDomainMap(map);
2838
2839 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) {
2840
2841 queriesCount++;
2842
2843 if (domain == externalCNAME) {
2844 setLWResult(res, 0, true, false, true);
2845 addRecordToLW(res, externalCNAME, QType::A, addr.toString(), DNSResourceRecord::ANSWER, 3600);
2846 return 1;
2847 }
2848
2849 return 0;
2850 });
2851
2852 vector<DNSRecord> ret;
2853 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 2854 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
2855 BOOST_CHECK_EQUAL(ret.size(), 2);
2856 BOOST_CHECK(ret[0].d_type == QType::CNAME);
2857 BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), externalCNAME.toString());
2858 BOOST_CHECK(ret[1].d_type == QType::A);
2859 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[1])->getCA().toString(), addr.toString());
2860 BOOST_CHECK_EQUAL(queriesCount, 1);
2861}
2862
2863BOOST_AUTO_TEST_CASE(test_auth_zone_nodata) {
2864 std::unique_ptr<SyncRes> sr;
895449a5 2865 initSR(sr);
3337c2f7
RG
2866
2867 primeHints();
2868
2869 size_t queriesCount = 0;
2870 const DNSName target("nodata.powerdns.com.");
2871 const DNSName authZone("powerdns.com");
2872
2873 SyncRes::AuthDomain ad;
2874 ad.d_name = authZone;
2875 DNSRecord dr;
2876 dr.d_place = DNSResourceRecord::ANSWER;
2877 dr.d_name = target;
2878 dr.d_type = QType::A;
2879 dr.d_ttl = 3600;
2880 dr.d_content = std::make_shared<ARecordContent>(ComboAddress("192.0.2.1"));
2881 ad.d_records.insert(dr);
2882
2883 dr.d_place = DNSResourceRecord::ANSWER;
2884 dr.d_name = authZone;
2885 dr.d_type = QType::SOA;
2886 dr.d_ttl = 3600;
2887 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2888 ad.d_records.insert(dr);
2889
2890 auto map = std::make_shared<SyncRes::domainmap_t>();
2891 (*map)[authZone] = ad;
2892 SyncRes::setDomainMap(map);
2893
2894 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) {
2895
2896 queriesCount++;
2897
2898 return 0;
2899 });
2900
2901 vector<DNSRecord> ret;
2902 int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
b7f378d1 2903 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
2904 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2905 BOOST_CHECK(ret[0].d_type == QType::SOA);
2906 BOOST_CHECK_EQUAL(queriesCount, 0);
2907}
2908
2909BOOST_AUTO_TEST_CASE(test_auth_zone_nx) {
2910 std::unique_ptr<SyncRes> sr;
895449a5 2911 initSR(sr);
3337c2f7
RG
2912
2913 primeHints();
2914
2915 size_t queriesCount = 0;
2916 const DNSName target("nx.powerdns.com.");
2917 const DNSName authZone("powerdns.com");
2918
2919 SyncRes::AuthDomain ad;
2920 ad.d_name = authZone;
2921 DNSRecord dr;
2922 dr.d_place = DNSResourceRecord::ANSWER;
2923 dr.d_name = DNSName("powerdns.com.");
2924 dr.d_type = QType::SOA;
2925 dr.d_ttl = 3600;
2926 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2927 ad.d_records.insert(dr);
2928
2929 auto map = std::make_shared<SyncRes::domainmap_t>();
2930 (*map)[authZone] = ad;
2931 SyncRes::setDomainMap(map);
2932
2933 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) {
2934
2935 queriesCount++;
2936
2937 return 0;
2938 });
2939
2940 vector<DNSRecord> ret;
2941 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
2942 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
2943 BOOST_REQUIRE_EQUAL(ret.size(), 1);
2944 BOOST_CHECK(ret[0].d_type == QType::SOA);
2945 BOOST_CHECK_EQUAL(queriesCount, 0);
2946}
2947
2948BOOST_AUTO_TEST_CASE(test_auth_zone_delegation) {
2949 std::unique_ptr<SyncRes> sr;
895449a5 2950 initSR(sr);
3337c2f7
RG
2951
2952 primeHints();
2953
2954 size_t queriesCount = 0;
2955 const DNSName target("www.test.powerdns.com.");
2956 const ComboAddress targetAddr("192.0.2.2");
2957 const DNSName ns("ns1.test.powerdns.com.");
2958 const ComboAddress nsAddr("192.0.2.1");
2959 const DNSName authZone("powerdns.com");
2960
2961 SyncRes::AuthDomain ad;
2962 ad.d_name = authZone;
2963 DNSRecord dr;
2964 dr.d_place = DNSResourceRecord::ANSWER;
2965 dr.d_name = authZone;
2966 dr.d_type = QType::SOA;
2967 dr.d_ttl = 3600;
2968 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
2969 ad.d_records.insert(dr);
2970
2971 dr.d_place = DNSResourceRecord::ANSWER;
2972 dr.d_name = DNSName("test.powerdns.com.");
2973 dr.d_type = QType::NS;
2974 dr.d_ttl = 3600;
2975 dr.d_content = std::make_shared<NSRecordContent>(ns);
2976 ad.d_records.insert(dr);
2977
2978 dr.d_place = DNSResourceRecord::ANSWER;
2979 dr.d_name = ns;
2980 dr.d_type = QType::A;
2981 dr.d_ttl = 3600;
2982 dr.d_content = std::make_shared<ARecordContent>(nsAddr);
2983 ad.d_records.insert(dr);
2984
2985 auto map = std::make_shared<SyncRes::domainmap_t>();
2986 (*map)[authZone] = ad;
2987 SyncRes::setDomainMap(map);
2988
2989 sr->setAsyncCallback([&queriesCount,target,targetAddr,nsAddr](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
2990
2991 queriesCount++;
2992 if (ip == ComboAddress(nsAddr.toString(), 53) && domain == target) {
2993 setLWResult(res, 0, true, false, true);
2994 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
2995 return 1;
2996 }
2997
2998 return 0;
2999 });
3000
3001 vector<DNSRecord> ret;
3002 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 3003 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
3004 BOOST_REQUIRE_EQUAL(ret.size(), 1);
3005 BOOST_CHECK(ret[0].d_type == QType::A);
3006 BOOST_CHECK_EQUAL(queriesCount, 1);
3007}
3008
3009BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point) {
3010 std::unique_ptr<SyncRes> sr;
895449a5 3011 initSR(sr);
3337c2f7
RG
3012
3013 primeHints();
3014
3015 size_t queriesCount = 0;
3016 const DNSName target("test.powerdns.com.");
3017 const ComboAddress targetAddr("192.0.2.2");
3018 const DNSName ns("ns1.test.powerdns.com.");
3019 const ComboAddress nsAddr("192.0.2.1");
3020 const DNSName authZone("powerdns.com");
3021
3022 SyncRes::AuthDomain ad;
3023 ad.d_name = authZone;
3024 DNSRecord dr;
3025 dr.d_place = DNSResourceRecord::ANSWER;
3026 dr.d_name = authZone;
3027 dr.d_type = QType::SOA;
3028 dr.d_ttl = 3600;
3029 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3030 ad.d_records.insert(dr);
3031
3032 dr.d_place = DNSResourceRecord::ANSWER;
3033 dr.d_name = DNSName("test.powerdns.com.");
3034 dr.d_type = QType::NS;
3035 dr.d_ttl = 3600;
3036 dr.d_content = std::make_shared<NSRecordContent>(ns);
3037 ad.d_records.insert(dr);
3038
3039 dr.d_place = DNSResourceRecord::ANSWER;
3040 dr.d_name = ns;
3041 dr.d_type = QType::A;
3042 dr.d_ttl = 3600;
3043 dr.d_content = std::make_shared<ARecordContent>(nsAddr);
3044 ad.d_records.insert(dr);
3045
3046 auto map = std::make_shared<SyncRes::domainmap_t>();
3047 (*map)[authZone] = ad;
3048 SyncRes::setDomainMap(map);
3049
3050 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) {
3051
3052 queriesCount++;
3053
3054 if (ip == ComboAddress(nsAddr.toString(), 53) && domain == target) {
3055 setLWResult(res, 0, true, false, true);
3056 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
3057 return 1;
3058 }
3059
3060 return 0;
3061 });
3062
3063 vector<DNSRecord> ret;
3064 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 3065 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
3066 BOOST_REQUIRE_EQUAL(ret.size(), 1);
3067 BOOST_CHECK(ret[0].d_type == QType::A);
3068 BOOST_CHECK_EQUAL(queriesCount, 1);
3069}
3070
3071BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard) {
3072 std::unique_ptr<SyncRes> sr;
895449a5 3073 initSR(sr);
3337c2f7
RG
3074
3075 primeHints();
3076
3077 size_t queriesCount = 0;
3078 const DNSName target("test.powerdns.com.");
3079 const ComboAddress targetAddr("192.0.2.2");
3080 const DNSName authZone("powerdns.com");
3081
3082 SyncRes::AuthDomain ad;
3083 ad.d_name = authZone;
3084 DNSRecord dr;
3085 dr.d_place = DNSResourceRecord::ANSWER;
3086 dr.d_name = authZone;
3087 dr.d_type = QType::SOA;
3088 dr.d_ttl = 3600;
3089 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3090 ad.d_records.insert(dr);
3091
3092 dr.d_place = DNSResourceRecord::ANSWER;
3093 dr.d_name = DNSName("*.powerdns.com.");
3094 dr.d_type = QType::A;
3095 dr.d_ttl = 3600;
3096 dr.d_content = std::make_shared<ARecordContent>(targetAddr);
3097 ad.d_records.insert(dr);
3098
3099 auto map = std::make_shared<SyncRes::domainmap_t>();
3100 (*map)[authZone] = ad;
3101 SyncRes::setDomainMap(map);
3102
3103 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) {
3104
3105 queriesCount++;
3106
3107 return 0;
3108 });
3109
3110 vector<DNSRecord> ret;
3111 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 3112 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
3113 BOOST_REQUIRE_EQUAL(ret.size(), 1);
3114 BOOST_CHECK(ret[0].d_type == QType::A);
3115 BOOST_CHECK_EQUAL(queriesCount, 0);
3116}
3117
3118BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata) {
3119 std::unique_ptr<SyncRes> sr;
895449a5 3120 initSR(sr);
3337c2f7
RG
3121
3122 primeHints();
3123
3124 size_t queriesCount = 0;
3125 const DNSName target("test.powerdns.com.");
3126 const ComboAddress targetAddr("192.0.2.2");
3127 const DNSName authZone("powerdns.com");
3128
3129 SyncRes::AuthDomain ad;
3130 ad.d_name = authZone;
3131 DNSRecord dr;
3132 dr.d_place = DNSResourceRecord::ANSWER;
3133 dr.d_name = authZone;
3134 dr.d_type = QType::SOA;
3135 dr.d_ttl = 3600;
3136 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3137 ad.d_records.insert(dr);
3138
3139 dr.d_place = DNSResourceRecord::ANSWER;
3140 dr.d_name = DNSName("*.powerdns.com.");
3141 dr.d_type = QType::A;
3142 dr.d_ttl = 3600;
3143 dr.d_content = std::make_shared<ARecordContent>(targetAddr);
3144 ad.d_records.insert(dr);
3145
3146 auto map = std::make_shared<SyncRes::domainmap_t>();
3147 (*map)[authZone] = ad;
3148 SyncRes::setDomainMap(map);
3149
3150 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) {
3151
3152 queriesCount++;
3153
3154 return 0;
3155 });
3156
3157 vector<DNSRecord> ret;
3158 int res = sr->beginResolve(target, QType(QType::AAAA), QClass::IN, ret);
b7f378d1 3159 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
3160 BOOST_REQUIRE_EQUAL(ret.size(), 1);
3161 BOOST_CHECK(ret[0].d_type == QType::SOA);
3162 BOOST_CHECK_EQUAL(queriesCount, 0);
3163}
3164
3165BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only) {
3166 std::unique_ptr<SyncRes> sr;
895449a5 3167 initSR(sr);
3337c2f7
RG
3168
3169 primeHints();
3170
3171 size_t queriesCount = 0;
3172 const DNSName target("powerdns.com.");
3173 const ComboAddress addr("192.0.2.5");
3174
3175 SyncRes::AuthDomain ad;
3176 ad.d_name = target;
3177 DNSRecord dr;
3178 dr.d_place = DNSResourceRecord::ANSWER;
3179 dr.d_name = target;
3180 dr.d_type = QType::SOA;
3181 dr.d_ttl = 3600;
3182 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
3183 ad.d_records.insert(dr);
3184
3185 dr.d_place = DNSResourceRecord::ANSWER;
3186 dr.d_name = target;
3187 dr.d_type = QType::A;
3188 dr.d_ttl = 3600;
3189 dr.d_content = std::make_shared<ARecordContent>(addr);
3190 ad.d_records.insert(dr);
3191
3192 auto map = std::make_shared<SyncRes::domainmap_t>();
3193 (*map)[target] = ad;
3194 SyncRes::setDomainMap(map);
3195
3196 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) {
3197
3198 queriesCount++;
3199 setLWResult(res, 0, true, false, true);
3200 addRecordToLW(res, domain, QType::A, "192.0.2.42");
3201 return 1;
3202 });
3203
3204 /* simulate a no-RD query */
3205 sr->setCacheOnly();
3206
3207 vector<DNSRecord> ret;
3208 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1 3209 BOOST_CHECK_EQUAL(res, RCode::NoError);
3337c2f7
RG
3210 BOOST_CHECK_EQUAL(ret.size(), 1);
3211 BOOST_CHECK(ret[0].d_type == QType::A);
3212 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
3213 BOOST_CHECK_EQUAL(queriesCount, 0);
3214}
3215
8455425c 3216BOOST_AUTO_TEST_CASE(test_dnssec_rrsig) {
8455425c
RG
3217 init();
3218
3219 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3220 dcke->create(dcke->getBits());
3221 // cerr<<dcke->convertToISC()<<endl;
3222 DNSSECPrivateKey dpk;
3223 dpk.d_flags = 256;
3224 dpk.setKey(dcke);
3225
3226 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
3227 recordcontents.push_back(getRecordContent(QType::A, "192.0.2.1"));
3228
3229 DNSName qname("powerdns.com.");
3230
3231 RRSIGRecordContent rrc;
3232 computeRRSIG(dpk, qname, qname, QType::A, 600, 300, rrc, recordcontents);
3233
3234 skeyset_t keyset;
3235 keyset.insert(std::make_shared<DNSKEYRecordContent>(dpk.getDNSKEY()));
3236
3237 std::vector<std::shared_ptr<RRSIGRecordContent> > sigs;
3238 sigs.push_back(std::make_shared<RRSIGRecordContent>(rrc));
3239
3240 BOOST_CHECK(validateWithKeySet(time(nullptr), qname, recordcontents, sigs, keyset));
3241}
3242
3243BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk) {
3244 std::unique_ptr<SyncRes> sr;
895449a5 3245 initSR(sr, true);
8455425c
RG
3246
3247 g_dnssecmode = DNSSECMode::ValidateAll;
3248
3249 primeHints();
3250 const DNSName target(".");
b7f378d1 3251 testkeysset_t keys;
8455425c
RG
3252
3253 auto luaconfsCopy = g_luaconfs.getCopy();
3254 luaconfsCopy.dsAnchors.clear();
3255 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
3256 g_luaconfs.setState(luaconfsCopy);
3257
3258 size_t queriesCount = 0;
3259
3260 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) {
3261 queriesCount++;
3262
3263 if (domain == target && type == QType::NS) {
3264
3265 setLWResult(res, 0, true, false, true);
3266 char addr[] = "a.root-servers.net.";
3267 for (char idx = 'a'; idx <= 'm'; idx++) {
3268 addr[0] = idx;
3269 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3270 }
3271
3272 addRRSIG(keys, res->d_records, domain, 300);
3273
3274 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3275 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3276
3277 return 1;
3278 } else if (domain == target && type == QType::DNSKEY) {
3279
3280 setLWResult(res, 0, true, false, true);
3281
3282 addDNSKEY(keys, domain, 300, res->d_records);
3283 addRRSIG(keys, res->d_records, domain, 300);
3284
3285 return 1;
3286 }
3287
3288 return 0;
3289 });
3290
3291 vector<DNSRecord> ret;
3292 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3293 BOOST_CHECK_EQUAL(res, RCode::NoError);
3294 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
8455425c
RG
3295 /* 13 NS + 1 RRSIG */
3296 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3297 BOOST_CHECK_EQUAL(queriesCount, 2);
b7f378d1
RG
3298
3299 /* again, to test the cache */
3300 ret.clear();
3301 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3302 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3303 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
b7f378d1
RG
3304 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3305 BOOST_CHECK_EQUAL(queriesCount, 2);
8455425c
RG
3306}
3307
3308BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk) {
3309 std::unique_ptr<SyncRes> sr;
895449a5 3310 initSR(sr, true);
8455425c
RG
3311
3312 g_dnssecmode = DNSSECMode::ValidateAll;
3313
3314 primeHints();
3315 const DNSName target(".");
b7f378d1
RG
3316 testkeysset_t zskeys;
3317 testkeysset_t kskeys;
8455425c
RG
3318
3319 /* Generate key material for "." */
3320 auto dckeZ = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3321 dckeZ->create(dckeZ->getBits());
3322 DNSSECPrivateKey ksk;
3323 ksk.d_flags = 257;
3324 ksk.setKey(dckeZ);
b7f378d1
RG
3325 DSRecordContent kskds = makeDSFromDNSKey(target, ksk.getDNSKEY(), DNSSECKeeper::SHA256);
3326
8455425c
RG
3327 auto dckeK = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3328 dckeK->create(dckeK->getBits());
3329 DNSSECPrivateKey zsk;
3330 zsk.d_flags = 256;
3331 zsk.setKey(dckeK);
b7f378d1 3332 DSRecordContent zskds = makeDSFromDNSKey(target, zsk.getDNSKEY(), DNSSECKeeper::SHA256);
8455425c 3333
b7f378d1
RG
3334 kskeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(ksk, kskds);
3335 zskeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(zsk, zskds);
8455425c
RG
3336
3337 /* Set the root DS */
8455425c
RG
3338 auto luaconfsCopy = g_luaconfs.getCopy();
3339 luaconfsCopy.dsAnchors.clear();
b7f378d1 3340 luaconfsCopy.dsAnchors[g_rootdnsname].insert(kskds);
8455425c
RG
3341 g_luaconfs.setState(luaconfsCopy);
3342
3343 size_t queriesCount = 0;
3344
3345 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) {
3346 queriesCount++;
3347
3348 if (domain == target && type == QType::NS) {
3349
3350 setLWResult(res, 0, true, false, true);
3351 char addr[] = "a.root-servers.net.";
3352 for (char idx = 'a'; idx <= 'm'; idx++) {
3353 addr[0] = idx;
3354 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3355 }
3356
3357 addRRSIG(zskeys, res->d_records, domain, 300);
3358
3359 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3360 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3361
3362 return 1;
3363 } else if (domain == target && type == QType::DNSKEY) {
3364
3365 setLWResult(res, 0, true, false, true);
3366
3367 addDNSKEY(kskeys, domain, 300, res->d_records);
3368 addDNSKEY(zskeys, domain, 300, res->d_records);
3369 addRRSIG(kskeys, res->d_records, domain, 300);
3370
3371 return 1;
3372 }
3373
3374 return 0;
3375 });
3376
3377 vector<DNSRecord> ret;
3378 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3379 BOOST_CHECK_EQUAL(res, RCode::NoError);
3380 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
8455425c
RG
3381 /* 13 NS + 1 RRSIG */
3382 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3383 BOOST_CHECK_EQUAL(queriesCount, 2);
b7f378d1
RG
3384
3385 /* again, to test the cache */
3386 ret.clear();
3387 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3388 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3389 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
b7f378d1
RG
3390 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3391 BOOST_CHECK_EQUAL(queriesCount, 2);
8455425c
RG
3392}
3393
3394BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey) {
3395 std::unique_ptr<SyncRes> sr;
895449a5 3396 initSR(sr, true);
8455425c
RG
3397
3398 g_dnssecmode = DNSSECMode::ValidateAll;
3399
3400 primeHints();
3401 const DNSName target(".");
b7f378d1 3402 testkeysset_t keys;
8455425c
RG
3403
3404 auto luaconfsCopy = g_luaconfs.getCopy();
3405 luaconfsCopy.dsAnchors.clear();
3406 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
3407 g_luaconfs.setState(luaconfsCopy);
3408
3409 size_t queriesCount = 0;
3410
3411 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) {
3412 queriesCount++;
3413
3414 if (domain == target && type == QType::NS) {
3415
3416 setLWResult(res, 0, true, false, true);
3417 char addr[] = "a.root-servers.net.";
3418 for (char idx = 'a'; idx <= 'm'; idx++) {
3419 addr[0] = idx;
3420 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3421 }
3422
3423 addRRSIG(keys, res->d_records, domain, 300);
3424
3425 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3426 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3427
3428 return 1;
3429 } else if (domain == target && type == QType::DNSKEY) {
3430
3431 setLWResult(res, 0, true, false, true);
3432
3433 /* No DNSKEY */
3434
3435 return 1;
3436 }
3437
3438 return 0;
3439 });
3440
3441 vector<DNSRecord> ret;
3442 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3443 BOOST_CHECK_EQUAL(res, RCode::NoError);
3444 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
8455425c
RG
3445 /* 13 NS + 1 RRSIG */
3446 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3447 BOOST_CHECK_EQUAL(queriesCount, 2);
b7f378d1
RG
3448
3449 /* again, to test the cache */
3450 ret.clear();
3451 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3452 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3453 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
b7f378d1
RG
3454 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3455 BOOST_CHECK_EQUAL(queriesCount, 2);
8455425c
RG
3456}
3457
3458BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds) {
3459 std::unique_ptr<SyncRes> sr;
895449a5 3460 initSR(sr, true);
8455425c
RG
3461
3462 g_dnssecmode = DNSSECMode::ValidateAll;
3463
3464 primeHints();
3465 const DNSName target(".");
b7f378d1
RG
3466 testkeysset_t dskeys;
3467 testkeysset_t keys;
8455425c
RG
3468
3469 /* Generate key material for "." */
3470 auto dckeDS = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3471 dckeDS->create(dckeDS->getBits());
3472 DNSSECPrivateKey dskey;
3473 dskey.d_flags = 257;
3474 dskey.setKey(dckeDS);
b7f378d1
RG
3475 DSRecordContent drc = makeDSFromDNSKey(target, dskey.getDNSKEY(), DNSSECKeeper::SHA256);
3476
8455425c
RG
3477 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3478 dcke->create(dcke->getBits());
3479 DNSSECPrivateKey dpk;
3480 dpk.d_flags = 256;
3481 dpk.setKey(dcke);
b7f378d1 3482 DSRecordContent uselessdrc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::SHA256);
8455425c 3483
b7f378d1
RG
3484 dskeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(dskey, drc);
3485 keys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(dpk, uselessdrc);
8455425c
RG
3486
3487 /* Set the root DS */
8455425c
RG
3488 auto luaconfsCopy = g_luaconfs.getCopy();
3489 luaconfsCopy.dsAnchors.clear();
3490 luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
3491 g_luaconfs.setState(luaconfsCopy);
3492
3493 size_t queriesCount = 0;
3494
3495 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) {
3496 queriesCount++;
3497
3498 if (domain == target && type == QType::NS) {
3499
3500 setLWResult(res, 0, true, false, true);
3501 char addr[] = "a.root-servers.net.";
3502 for (char idx = 'a'; idx <= 'm'; idx++) {
3503 addr[0] = idx;
3504 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3505 }
3506
3507 addRRSIG(keys, res->d_records, domain, 300);
3508
3509 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3510 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3511
3512 return 1;
3513 } else if (domain == target && type == QType::DNSKEY) {
3514
3515 setLWResult(res, 0, true, false, true);
3516
3517 addDNSKEY(keys, domain, 300, res->d_records);
3518 addRRSIG(keys, res->d_records, domain, 300);
3519
3520 return 1;
3521 }
3522
3523 return 0;
3524 });
3525
3526 vector<DNSRecord> ret;
3527 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3528 BOOST_CHECK_EQUAL(res, RCode::NoError);
3529 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
8455425c
RG
3530 /* 13 NS + 1 RRSIG */
3531 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3532 BOOST_CHECK_EQUAL(queriesCount, 2);
b7f378d1
RG
3533
3534 /* again, to test the cache */
3535 ret.clear();
3536 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3537 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3538 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
b7f378d1
RG
3539 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3540 BOOST_CHECK_EQUAL(queriesCount, 2);
8455425c
RG
3541}
3542
3543BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey) {
3544 std::unique_ptr<SyncRes> sr;
895449a5 3545 initSR(sr, true);
8455425c
RG
3546
3547 g_dnssecmode = DNSSECMode::ValidateAll;
3548
3549 primeHints();
3550 const DNSName target(".");
b7f378d1
RG
3551 testkeysset_t keys;
3552 testkeysset_t rrsigkeys;
8455425c
RG
3553
3554 auto luaconfsCopy = g_luaconfs.getCopy();
3555 luaconfsCopy.dsAnchors.clear();
3556 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
3557 g_luaconfs.setState(luaconfsCopy);
3558
3559 auto dckeRRSIG = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3560 dckeRRSIG->create(dckeRRSIG->getBits());
3561 DNSSECPrivateKey rrsigkey;
3562 rrsigkey.d_flags = 257;
3563 rrsigkey.setKey(dckeRRSIG);
b7f378d1
RG
3564 DSRecordContent rrsigds = makeDSFromDNSKey(target, rrsigkey.getDNSKEY(), DNSSECKeeper::SHA256);
3565
3566 rrsigkeys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(rrsigkey, rrsigds);
8455425c
RG
3567
3568 size_t queriesCount = 0;
3569
3570 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) {
3571 queriesCount++;
3572
3573 if (domain == target && type == QType::NS) {
3574
3575 setLWResult(res, 0, true, false, true);
3576 char addr[] = "a.root-servers.net.";
3577 for (char idx = 'a'; idx <= 'm'; idx++) {
3578 addr[0] = idx;
3579 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3580 }
3581
3582 addRRSIG(rrsigkeys, res->d_records, domain, 300);
3583
3584 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3585 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3586
3587 return 1;
3588 } else if (domain == target && type == QType::DNSKEY) {
3589
3590 setLWResult(res, 0, true, false, true);
3591
3592 addDNSKEY(keys, domain, 300, res->d_records);
3593 addRRSIG(rrsigkeys, res->d_records, domain, 300);
3594
3595 return 1;
3596 }
3597
3598 return 0;
3599 });
3600
3601 vector<DNSRecord> ret;
3602 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3603 BOOST_CHECK_EQUAL(res, RCode::NoError);
3604 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
8455425c
RG
3605 /* 13 NS + 1 RRSIG */
3606 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3607 BOOST_CHECK_EQUAL(queriesCount, 2);
b7f378d1
RG
3608
3609 /* again, to test the cache */
3610 ret.clear();
3611 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3612 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3613 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
b7f378d1
RG
3614 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3615 BOOST_CHECK_EQUAL(queriesCount, 2);
8455425c
RG
3616}
3617
3618BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig) {
3619 std::unique_ptr<SyncRes> sr;
895449a5 3620 initSR(sr, true);
8455425c
RG
3621
3622 g_dnssecmode = DNSSECMode::ValidateAll;
3623
3624 primeHints();
3625 const DNSName target(".");
b7f378d1 3626 testkeysset_t keys;
8455425c
RG
3627
3628 auto luaconfsCopy = g_luaconfs.getCopy();
3629 luaconfsCopy.dsAnchors.clear();
3630 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
3631 g_luaconfs.setState(luaconfsCopy);
3632
3633 size_t queriesCount = 0;
3634
3635 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) {
3636 queriesCount++;
3637
3638 if (domain == target && type == QType::NS) {
3639
3640 setLWResult(res, 0, true, false, true);
3641 char addr[] = "a.root-servers.net.";
3642 for (char idx = 'a'; idx <= 'm'; idx++) {
3643 addr[0] = idx;
3644 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3645 }
3646
3647 /* No RRSIG */
3648
3649 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3650 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3651
3652 return 1;
3653 } else if (domain == target && type == QType::DNSKEY) {
3654
3655 setLWResult(res, 0, true, false, true);
3656
3657 addDNSKEY(keys, domain, 300, res->d_records);
3658 addRRSIG(keys, res->d_records, domain, 300);
3659
3660 return 1;
3661 }
3662
3663 return 0;
3664 });
3665
3666 vector<DNSRecord> ret;
3667 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3668 BOOST_CHECK_EQUAL(res, RCode::NoError);
3669 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
8455425c
RG
3670 /* 13 NS + 0 RRSIG */
3671 BOOST_REQUIRE_EQUAL(ret.size(), 13);
3672 /* no RRSIG so no query for DNSKEYs */
3673 BOOST_CHECK_EQUAL(queriesCount, 1);
b7f378d1
RG
3674
3675 /* again, to test the cache */
3676 ret.clear();
3677 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3678 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3679 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
b7f378d1
RG
3680 BOOST_REQUIRE_EQUAL(ret.size(), 13);
3681 BOOST_CHECK_EQUAL(queriesCount, 1);
8455425c
RG
3682}
3683
3684BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm) {
3685 std::unique_ptr<SyncRes> sr;
895449a5 3686 initSR(sr, true);
8455425c
RG
3687
3688 g_dnssecmode = DNSSECMode::ValidateAll;
3689
3690 primeHints();
3691 const DNSName target(".");
b7f378d1 3692 testkeysset_t keys;
8455425c
RG
3693
3694 /* Generate key material for "." */
3695 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3696 dcke->create(dcke->getBits());
3697 DNSSECPrivateKey dpk;
3698 dpk.d_flags = 256;
3699 dpk.setKey(dcke);
3700 /* Fake algorithm number (private) */
3701 dpk.d_algorithm = 253;
3702
8455425c 3703 DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::SHA256);
b7f378d1 3704 keys[target] = std::pair<DNSSECPrivateKey,DSRecordContent>(dpk, drc);
8455425c
RG
3705 /* Fake algorithm number (private) */
3706 drc.d_algorithm = 253;
3707
b7f378d1 3708 /* Set the root DS */
8455425c
RG
3709 auto luaconfsCopy = g_luaconfs.getCopy();
3710 luaconfsCopy.dsAnchors.clear();
3711 luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
3712 g_luaconfs.setState(luaconfsCopy);
3713
3714 size_t queriesCount = 0;
3715
3716 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) {
3717 queriesCount++;
3718
3719 if (domain == target && type == QType::NS) {
3720
3721 setLWResult(res, 0, true, false, true);
3722 char addr[] = "a.root-servers.net.";
3723 for (char idx = 'a'; idx <= 'm'; idx++) {
3724 addr[0] = idx;
3725 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3726 }
3727
3728 addRRSIG(keys, res->d_records, domain, 300);
3729
3730 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3731 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3732
3733 return 1;
3734 } else if (domain == target && type == QType::DNSKEY) {
3735
3736 setLWResult(res, 0, true, false, true);
3737
3738 addDNSKEY(keys, domain, 300, res->d_records);
3739 addRRSIG(keys, res->d_records, domain, 300);
3740
3741 return 1;
3742 }
3743
3744 return 0;
3745 });
3746
3747 vector<DNSRecord> ret;
3748 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3749 BOOST_CHECK_EQUAL(res, RCode::NoError);
3750 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
8455425c
RG
3751 /* 13 NS + 1 RRSIG */
3752 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3753 /* no supported DS so no query for DNSKEYs */
3754 BOOST_CHECK_EQUAL(queriesCount, 1);
b7f378d1
RG
3755
3756 /* again, to test the cache */
3757 ret.clear();
3758 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3759 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3760 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
b7f378d1
RG
3761 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3762 BOOST_CHECK_EQUAL(queriesCount, 1);
8455425c
RG
3763}
3764
3765BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest) {
3766 std::unique_ptr<SyncRes> sr;
895449a5 3767 initSR(sr, true);
8455425c
RG
3768
3769 g_dnssecmode = DNSSECMode::ValidateAll;
3770
3771 primeHints();
3772 const DNSName target(".");
b7f378d1 3773 testkeysset_t keys;
8455425c
RG
3774
3775 /* Generate key material for "." */
3776 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(DNSSECKeeper::ECDSA256));
3777 dcke->create(dcke->getBits());
3778 DNSSECPrivateKey dpk;
3779 dpk.d_flags = 256;
3780 dpk.setKey(dcke);
8455425c
RG
3781 DSRecordContent drc = makeDSFromDNSKey(target, dpk.getDNSKEY(), DNSSECKeeper::SHA256);
3782 /* Fake digest number (reserved) */
3783 drc.d_digesttype = 0;
3784
b7f378d1
RG
3785 keys[target] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, drc);
3786
3787 /* Set the root DS */
8455425c
RG
3788 auto luaconfsCopy = g_luaconfs.getCopy();
3789 luaconfsCopy.dsAnchors.clear();
3790 luaconfsCopy.dsAnchors[g_rootdnsname].insert(drc);
3791 g_luaconfs.setState(luaconfsCopy);
3792
3793 size_t queriesCount = 0;
3794
3795 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) {
3796 queriesCount++;
3797
3798 if (domain == target && type == QType::NS) {
3799
3800 setLWResult(res, 0, true, false, true);
3801 char addr[] = "a.root-servers.net.";
3802 for (char idx = 'a'; idx <= 'm'; idx++) {
3803 addr[0] = idx;
3804 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3805 }
3806
3807 addRRSIG(keys, res->d_records, domain, 300);
3808
3809 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3810 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3811
3812 return 1;
3813 } else if (domain == target && type == QType::DNSKEY) {
3814
3815 setLWResult(res, 0, true, false, true);
3816
3817 addDNSKEY(keys, domain, 300, res->d_records);
3818 addRRSIG(keys, res->d_records, domain, 300);
3819
3820 return 1;
3821 }
3822
3823 return 0;
3824 });
3825
3826 vector<DNSRecord> ret;
3827 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
3828 BOOST_CHECK_EQUAL(res, RCode::NoError);
3829 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
8455425c
RG
3830 /* 13 NS + 1 RRSIG */
3831 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3832 /* no supported DS so no query for DNSKEYs */
3833 BOOST_CHECK_EQUAL(queriesCount, 1);
b7f378d1
RG
3834
3835 /* again, to test the cache */
3836 ret.clear();
3837 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3838 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 3839 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
b7f378d1
RG
3840 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3841 BOOST_CHECK_EQUAL(queriesCount, 1);
8455425c
RG
3842}
3843
3d5ebf10
RG
3844BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig) {
3845 std::unique_ptr<SyncRes> sr;
3846 initSR(sr, true);
3847
3848 g_dnssecmode = DNSSECMode::ValidateAll;
3849
3850 primeHints();
3851 const DNSName target(".");
3852 testkeysset_t keys;
3853
3854 auto luaconfsCopy = g_luaconfs.getCopy();
3855 luaconfsCopy.dsAnchors.clear();
3856 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::SHA384, keys, luaconfsCopy.dsAnchors);
3857
3858 g_luaconfs.setState(luaconfsCopy);
3859
3860 size_t queriesCount = 0;
3861
3862 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) {
3863 queriesCount++;
3864
3865 if (domain == target && type == QType::NS) {
3866
3867 setLWResult(res, 0, true, false, true);
3868 char addr[] = "a.root-servers.net.";
3869 for (char idx = 'a'; idx <= 'm'; idx++) {
3870 addr[0] = idx;
3871 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3872 }
3873
3874 addRRSIG(keys, res->d_records, domain, 300, true);
3875
3876 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3877 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3878
3879 return 1;
3880 } else if (domain == target && type == QType::DNSKEY) {
3881
3882 setLWResult(res, 0, true, false, true);
3883
3884 addDNSKEY(keys, domain, 300, res->d_records);
3885 addRRSIG(keys, res->d_records, domain, 300);
3886
3887 return 1;
3888 }
3889
3890 return 0;
3891 });
3892
3893 vector<DNSRecord> ret;
3894 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3895 BOOST_CHECK_EQUAL(res, RCode::NoError);
3896 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
3897 /* 13 NS + 1 RRSIG */
3898 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3899 BOOST_CHECK_EQUAL(queriesCount, 2);
3900
3901 /* again, to test the cache */
3902 ret.clear();
3903 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3904 BOOST_CHECK_EQUAL(res, RCode::NoError);
3905 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
3906 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3907 BOOST_CHECK_EQUAL(queriesCount, 2);
3908}
3909
3910BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo) {
3911 std::unique_ptr<SyncRes> sr;
3912 initSR(sr, true);
3913
3914 g_dnssecmode = DNSSECMode::ValidateAll;
3915
3916 primeHints();
3917 const DNSName target(".");
3918 testkeysset_t keys;
3919
3920 auto luaconfsCopy = g_luaconfs.getCopy();
3921 luaconfsCopy.dsAnchors.clear();
3922 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::SHA384, keys, luaconfsCopy.dsAnchors);
3923
3924 g_luaconfs.setState(luaconfsCopy);
3925
3926 size_t queriesCount = 0;
3927
3928 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) {
3929 queriesCount++;
3930
3931 if (domain == target && type == QType::NS) {
3932
3933 setLWResult(res, 0, true, false, true);
3934 char addr[] = "a.root-servers.net.";
3935 for (char idx = 'a'; idx <= 'm'; idx++) {
3936 addr[0] = idx;
3937 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
3938 }
3939
3940 /* FORCE WRONG ALGO */
3941 addRRSIG(keys, res->d_records, domain, 300, false, DNSSECKeeper::RSASHA256);
3942
3943 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
3944 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
3945
3946 return 1;
3947 } else if (domain == target && type == QType::DNSKEY) {
3948
3949 setLWResult(res, 0, true, false, true);
3950
3951 addDNSKEY(keys, domain, 300, res->d_records);
3952 addRRSIG(keys, res->d_records, domain, 300);
3953
3954 return 1;
3955 }
3956
3957 return 0;
3958 });
3959
3960 vector<DNSRecord> ret;
3961 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3962 BOOST_CHECK_EQUAL(res, RCode::NoError);
3963 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
3964 /* 13 NS + 1 RRSIG */
3965 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3966 BOOST_CHECK_EQUAL(queriesCount, 2);
3967
3968 /* again, to test the cache */
3969 ret.clear();
3970 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
3971 BOOST_CHECK_EQUAL(res, RCode::NoError);
3972 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
3973 BOOST_REQUIRE_EQUAL(ret.size(), 14);
3974 BOOST_CHECK_EQUAL(queriesCount, 2);
3975}
3976
b7f378d1 3977BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos) {
8455425c 3978 std::unique_ptr<SyncRes> sr;
895449a5 3979 initSR(sr, true);
8455425c
RG
3980
3981 g_dnssecmode = DNSSECMode::ValidateAll;
3982
3983 primeHints();
3984 const DNSName target("powerdns.com.");
b7f378d1
RG
3985 const ComboAddress targetAddr("192.0.2.42");
3986 testkeysset_t keys;
8455425c
RG
3987
3988 auto luaconfsCopy = g_luaconfs.getCopy();
3989 luaconfsCopy.dsAnchors.clear();
b7f378d1
RG
3990 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, DNSSECKeeper::SHA384, keys, luaconfsCopy.dsAnchors);
3991 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
3992 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA384, DNSSECKeeper::SHA384, keys);
8455425c
RG
3993
3994 g_luaconfs.setState(luaconfsCopy);
3995
3996 size_t queriesCount = 0;
3997
b7f378d1 3998 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) {
8455425c
RG
3999 queriesCount++;
4000
b7f378d1
RG
4001 DNSName auth = domain;
4002 if (domain == target) {
4003 auth = DNSName("powerdns.com.");
4004 }
8455425c 4005 if (type == QType::DS) {
a53e8fe3 4006 return 0;
8455425c
RG
4007 }
4008 else if (type == QType::DNSKEY) {
4009 setLWResult(res, 0, true, false, true);
b7f378d1
RG
4010 addDNSKEY(keys, auth, 300, res->d_records);
4011 addRRSIG(keys, res->d_records, auth, 300);
8455425c
RG
4012 return 1;
4013 }
f24465e5 4014 else {
8455425c
RG
4015 if (isRootServer(ip)) {
4016 setLWResult(res, 0, false, false, true);
4017 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
b7f378d1 4018 addDS(DNSName("com."), 300, res->d_records, keys);
8455425c
RG
4019 addRRSIG(keys, res->d_records, DNSName("."), 300);
4020 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4021 return 1;
4022 }
4023 else if (ip == ComboAddress("192.0.2.1:53")) {
f24465e5
RG
4024 if (domain == DNSName("com.")) {
4025 setLWResult(res, 0, true, false, true);
4026 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
4027 addRRSIG(keys, res->d_records, domain, 300);
4028 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4029 addRRSIG(keys, res->d_records, domain, 300);
4030 }
4031 else {
4032 setLWResult(res, 0, false, false, true);
4033 addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4034 addDS(auth, 300, res->d_records, keys);
4035 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4036 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4037 }
8455425c
RG
4038 return 1;
4039 }
4040 else if (ip == ComboAddress("192.0.2.2:53")) {
f24465e5
RG
4041 if (type == QType::NS) {
4042 setLWResult(res, 0, true, false, true);
4043 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4044 addRRSIG(keys, res->d_records, auth, 300);
4045 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4046 addRRSIG(keys, res->d_records, auth, 300);
4047 }
4048 else {
4049 setLWResult(res, RCode::NoError, true, false, true);
4050 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
4051 addRRSIG(keys, res->d_records, auth, 300);
4052 }
8455425c
RG
4053 return 1;
4054 }
4055 }
4056
4057 return 0;
4058 });
4059
4060 vector<DNSRecord> ret;
4061 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
b7f378d1
RG
4062 BOOST_CHECK_EQUAL(res, RCode::NoError);
4063 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
4064 BOOST_REQUIRE_EQUAL(ret.size(), 2);
f24465e5 4065 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4066
4067 /* again, to test the cache */
4068 ret.clear();
4069 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4070 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 4071 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
b7f378d1 4072 BOOST_REQUIRE_EQUAL(ret.size(), 2);
f24465e5 4073 BOOST_CHECK_EQUAL(queriesCount, 8);
8455425c
RG
4074}
4075
b7f378d1 4076BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta) {
8455425c 4077 std::unique_ptr<SyncRes> sr;
895449a5 4078 initSR(sr, true);
8455425c
RG
4079
4080 g_dnssecmode = DNSSECMode::ValidateAll;
4081
4082 primeHints();
b7f378d1
RG
4083 const DNSName target("powerdns.com.");
4084 const ComboAddress targetAddr("192.0.2.42");
4085 testkeysset_t keys;
8455425c
RG
4086
4087 auto luaconfsCopy = g_luaconfs.getCopy();
4088 luaconfsCopy.dsAnchors.clear();
b7f378d1
RG
4089 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4090 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4091 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4092
4093 /* Add a NTA for "powerdns.com" */
4094 luaconfsCopy.negAnchors[target] = "NTA for PowerDNS.com";
8455425c 4095
8455425c
RG
4096 g_luaconfs.setState(luaconfsCopy);
4097
4098 size_t queriesCount = 0;
4099
b7f378d1 4100 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) {
8455425c
RG
4101 queriesCount++;
4102
b7f378d1
RG
4103 DNSName auth = domain;
4104 if (domain == target) {
4105 auth = DNSName("powerdns.com.");
4106 }
4107 if (type == QType::DS) {
a53e8fe3 4108 return 0;
b7f378d1
RG
4109 }
4110 else if (type == QType::DNSKEY) {
8455425c 4111 setLWResult(res, 0, true, false, true);
b7f378d1
RG
4112 addDNSKEY(keys, auth, 300, res->d_records);
4113 addRRSIG(keys, res->d_records, auth, 300);
4114 return 1;
4115 }
f24465e5 4116 else {
b7f378d1
RG
4117 if (isRootServer(ip)) {
4118 setLWResult(res, 0, false, false, true);
4119 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4120 addDS(DNSName("com."), 300, res->d_records, keys);
4121 addRRSIG(keys, res->d_records, DNSName("."), 300);
4122 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4123 return 1;
4124 }
4125 else if (ip == ComboAddress("192.0.2.1:53")) {
f24465e5
RG
4126 if (domain == DNSName("com.")) {
4127 setLWResult(res, 0, true, false, true);
4128 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
4129 addRRSIG(keys, res->d_records, domain, 300);
4130 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4131 addRRSIG(keys, res->d_records, domain, 300);
4132 }
4133 else {
4134 setLWResult(res, 0, false, false, true);
4135 addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4136 addDS(auth, 300, res->d_records, keys);
4137 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4138 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4139 }
b7f378d1
RG
4140 return 1;
4141 }
4142 else if (ip == ComboAddress("192.0.2.2:53")) {
f24465e5
RG
4143 if (type == QType::NS) {
4144 setLWResult(res, 0, true, false, true);
4145 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4146 addRRSIG(keys, res->d_records, auth, 300);
4147 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4148 addRRSIG(keys, res->d_records, auth, 300);
4149 }
4150 else {
4151 setLWResult(res, RCode::NoError, true, false, true);
4152 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
4153 addRRSIG(keys, res->d_records, auth, 300);
4154 }
b7f378d1
RG
4155 return 1;
4156 }
4157 }
4158
4159 return 0;
4160 });
4161
4162 vector<DNSRecord> ret;
4163 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4164 BOOST_CHECK_EQUAL(res, RCode::NoError);
4165 /* Should be insecure because of the NTA */
4166 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
4167 BOOST_REQUIRE_EQUAL(ret.size(), 2);
f24465e5 4168 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4169
4170 /* again, to test the cache */
4171 ret.clear();
4172 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4173 BOOST_CHECK_EQUAL(res, RCode::NoError);
4174 /* Should be insecure because of the NTA */
4175 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
4176 BOOST_REQUIRE_EQUAL(ret.size(), 2);
f24465e5 4177 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4178}
4179
4180BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta) {
4181 std::unique_ptr<SyncRes> sr;
895449a5 4182 initSR(sr, true);
b7f378d1
RG
4183
4184 g_dnssecmode = DNSSECMode::ValidateAll;
4185
4186 primeHints();
4187 const DNSName target("powerdns.com.");
4188 const ComboAddress targetAddr("192.0.2.42");
4189 testkeysset_t keys;
4190
4191 auto luaconfsCopy = g_luaconfs.getCopy();
4192 luaconfsCopy.dsAnchors.clear();
4193 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4194 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4195 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4196
4197 /* Add a NTA for "powerdns.com" */
4198 luaconfsCopy.negAnchors[target] = "NTA for PowerDNS.com";
4199
4200 g_luaconfs.setState(luaconfsCopy);
4201
4202 size_t queriesCount = 0;
4203
4204 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) {
4205 queriesCount++;
4206
4207 if (type == QType::DS || type == QType::DNSKEY) {
4208 setLWResult(res, 0, false, false, true);
4209 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4210 return 1;
4211 }
f24465e5 4212 else {
b7f378d1
RG
4213 if (isRootServer(ip)) {
4214 setLWResult(res, 0, false, false, true);
4215 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4216 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4217 return 1;
4218 }
4219 else if (ip == ComboAddress("192.0.2.1:53")) {
f24465e5
RG
4220 if (domain == DNSName("com.")) {
4221 setLWResult(res, 0, true, false, true);
4222 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
4223 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4224 }
4225 else {
4226 setLWResult(res, 0, false, false, true);
4227 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4228 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4229 }
b7f378d1
RG
4230 return 1;
4231 }
4232 else if (ip == ComboAddress("192.0.2.2:53")) {
f24465e5
RG
4233 if (type == QType::NS) {
4234 setLWResult(res, 0, true, false, true);
4235 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4236 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4237 }
4238 else {
4239 setLWResult(res, RCode::NoError, true, false, true);
4240 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
4241 }
b7f378d1
RG
4242 return 1;
4243 }
4244 }
4245
4246 return 0;
4247 });
4248
4249 /* There is TA for root but no DS/DNSKEY/RRSIG, should be Bogus, but.. */
4250 vector<DNSRecord> ret;
4251 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4252 BOOST_CHECK_EQUAL(res, RCode::NoError);
4253 /* Should be insecure because of the NTA */
4254 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
4255 BOOST_REQUIRE_EQUAL(ret.size(), 1);
4256 /* and a such, no query for the DNSKEYs */
f24465e5 4257 BOOST_CHECK_EQUAL(queriesCount, 6);
b7f378d1
RG
4258
4259 /* again, to test the cache */
4260 ret.clear();
4261 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4262 BOOST_CHECK_EQUAL(res, RCode::NoError);
4263 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
4264 BOOST_REQUIRE_EQUAL(ret.size(), 1);
f24465e5 4265 BOOST_CHECK_EQUAL(queriesCount, 6);
b7f378d1
RG
4266}
4267
4268BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec) {
4269 std::unique_ptr<SyncRes> sr;
895449a5 4270 initSR(sr, true);
b7f378d1
RG
4271
4272 g_dnssecmode = DNSSECMode::ValidateAll;
4273
4274 primeHints();
4275 const DNSName target("powerdns.com.");
4276 testkeysset_t keys;
4277
4278 auto luaconfsCopy = g_luaconfs.getCopy();
4279 luaconfsCopy.dsAnchors.clear();
4280 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4281 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4282 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4283
4284 g_luaconfs.setState(luaconfsCopy);
4285
4286 size_t queriesCount = 0;
4287
4288 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) {
4289 queriesCount++;
4290
4291 if (type == QType::DS) {
a53e8fe3 4292 return 0;
b7f378d1
RG
4293 }
4294 else if (type == QType::DNSKEY) {
4295 setLWResult(res, 0, true, false, true);
4296 addDNSKEY(keys, domain, 300, res->d_records);
4297 addRRSIG(keys, res->d_records, domain, 300);
4298 return 1;
4299 }
f24465e5 4300 else {
b7f378d1
RG
4301 if (isRootServer(ip)) {
4302 setLWResult(res, 0, false, false, true);
4303 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4304 addDS(DNSName("com."), 300, res->d_records, keys);
4305 addRRSIG(keys, res->d_records, DNSName("."), 300);
4306 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4307 return 1;
4308 }
4309 else if (ip == ComboAddress("192.0.2.1:53")) {
f24465e5
RG
4310 if (domain == DNSName("com.")) {
4311 setLWResult(res, 0, true, false, true);
4312 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
4313 addRRSIG(keys, res->d_records, domain, 300);
4314 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4315 addRRSIG(keys, res->d_records, domain, 300);
4316 }
4317 else {
4318 setLWResult(res, 0, false, false, true);
4319 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4320 addDS(domain, 300, res->d_records, keys);
4321 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4322 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4323 }
b7f378d1
RG
4324 return 1;
4325 }
4326 else if (ip == ComboAddress("192.0.2.2:53")) {
f24465e5
RG
4327 if (type == QType::NS) {
4328 setLWResult(res, 0, true, false, true);
4329 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4330 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4331 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4332 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4333 }
4334 else {
4335 setLWResult(res, 0, true, false, true);
4336 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4337 addRRSIG(keys, res->d_records, domain, 300);
4338 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS, QType::DNSKEY }, 600, res->d_records);
4339 addRRSIG(keys, res->d_records, domain, 300);
4340 }
b7f378d1
RG
4341 return 1;
4342 }
4343 }
4344
4345 return 0;
4346 });
4347
4348 vector<DNSRecord> ret;
4349 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4350 BOOST_CHECK_EQUAL(res, RCode::NoError);
4351 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
4352 BOOST_REQUIRE_EQUAL(ret.size(), 4);
f24465e5 4353 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4354
4355 /* again, to test the cache */
4356 ret.clear();
4357 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4358 BOOST_CHECK_EQUAL(res, RCode::NoError);
4359 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
4360 BOOST_REQUIRE_EQUAL(ret.size(), 4);
f24465e5 4361 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4362}
4363
4364BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec) {
4365 std::unique_ptr<SyncRes> sr;
895449a5 4366 initSR(sr, true);
b7f378d1
RG
4367
4368 g_dnssecmode = DNSSECMode::ValidateAll;
4369
4370 primeHints();
4371 const DNSName target("nx.powerdns.com.");
4372 testkeysset_t keys;
4373
4374 auto luaconfsCopy = g_luaconfs.getCopy();
4375 luaconfsCopy.dsAnchors.clear();
4376 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4377 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4378 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4379
4380 g_luaconfs.setState(luaconfsCopy);
4381
4382 size_t queriesCount = 0;
4383
4384 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) {
4385 queriesCount++;
4386
4387 DNSName auth = domain;
4388 if (domain == target) {
4389 auth = DNSName("powerdns.com.");
4390 }
4391 if (type == QType::DS) {
a53e8fe3 4392 return 0;
b7f378d1
RG
4393 }
4394 else if (type == QType::DNSKEY) {
4395 setLWResult(res, 0, true, false, true);
4396 addDNSKEY(keys, auth, 300, res->d_records);
4397 addRRSIG(keys, res->d_records, auth, 300);
4398 return 1;
4399 }
f24465e5 4400 else {
b7f378d1
RG
4401 if (isRootServer(ip)) {
4402 setLWResult(res, 0, false, false, true);
4403 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4404 addDS(DNSName("com."), 300, res->d_records, keys);
4405 addRRSIG(keys, res->d_records, DNSName("."), 300);
4406 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4407 return 1;
4408 }
4409 else if (ip == ComboAddress("192.0.2.1:53")) {
f24465e5
RG
4410 if (domain == DNSName("com.")) {
4411 setLWResult(res, 0, true, false, true);
4412 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
4413 addRRSIG(keys, res->d_records, domain, 300);
4414 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4415 addRRSIG(keys, res->d_records, domain, 300);
4416 }
4417 else {
4418 setLWResult(res, 0, false, false, true);
4419 addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4420 addDS(auth, 300, res->d_records, keys);
4421 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4422 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4423 }
b7f378d1
RG
4424 return 1;
4425 }
4426 else if (ip == ComboAddress("192.0.2.2:53")) {
f24465e5
RG
4427 if (type == QType::NS) {
4428 setLWResult(res, 0, true, false, true);
4429 if (domain == DNSName("powerdns.com.")) {
4430 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4431 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4432 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4433 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4434 }
4435 else {
4436 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4437 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4438 addNSECRecordToLW(DNSName("nx.powerdns.com."), DNSName("nz.powerdns.com."), { QType::A, QType::NSEC, QType::RRSIG }, 600, res->d_records);
4439 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4440 }
4441 }
4442 else {
4443 setLWResult(res, RCode::NXDomain, true, false, true);
4444 addRecordToLW(res, DNSName("powerdns.com."), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4445 addRRSIG(keys, res->d_records, auth, 300);
4446 addNSECRecordToLW(DNSName("nw.powerdns.com."), DNSName("ny.powerdns.com."), { QType::RRSIG, QType::NSEC }, 600, res->d_records);
4447 addRRSIG(keys, res->d_records, auth, 300);
4448 }
b7f378d1
RG
4449 return 1;
4450 }
4451 }
4452
4453 return 0;
4454 });
4455
4456 vector<DNSRecord> ret;
4457 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4458 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
4459 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
4460 BOOST_REQUIRE_EQUAL(ret.size(), 4);
f24465e5 4461 BOOST_CHECK_EQUAL(queriesCount, 9);
b7f378d1
RG
4462
4463 /* again, to test the cache */
4464 ret.clear();
4465 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4466 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
4467 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
4468 BOOST_REQUIRE_EQUAL(ret.size(), 4);
f24465e5 4469 BOOST_CHECK_EQUAL(queriesCount, 9);
b7f378d1
RG
4470}
4471
2b984251
RG
4472BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard) {
4473 std::unique_ptr<SyncRes> sr;
4474 initSR(sr, true);
4475
4476 g_dnssecmode = DNSSECMode::ValidateAll;
4477
4478 primeHints();
4479 const DNSName target("www.powerdns.com.");
4480 testkeysset_t keys;
4481
4482 auto luaconfsCopy = g_luaconfs.getCopy();
4483 luaconfsCopy.dsAnchors.clear();
4484 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4485 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4486 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4487
4488 g_luaconfs.setState(luaconfsCopy);
4489
4490 size_t queriesCount = 0;
4491
4492 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) {
4493 queriesCount++;
4494
4495 if (type == QType::DS) {
a53e8fe3 4496 return 0;
2b984251
RG
4497 }
4498 else if (type == QType::DNSKEY) {
4499 setLWResult(res, 0, true, false, true);
4500 addDNSKEY(keys, domain, 300, res->d_records);
4501 addRRSIG(keys, res->d_records, domain, 300);
4502 return 1;
4503 }
f24465e5 4504 else {
2b984251
RG
4505 if (isRootServer(ip)) {
4506 setLWResult(res, 0, false, false, true);
4507 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4508 addDS(DNSName("com."), 300, res->d_records, keys);
4509 addRRSIG(keys, res->d_records, DNSName("."), 300);
4510 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4511 return 1;
4512 }
4513 else if (ip == ComboAddress("192.0.2.1:53")) {
f24465e5
RG
4514 if (domain == DNSName("com.")) {
4515 setLWResult(res, 0, true, false, true);
4516 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
4517 addRRSIG(keys, res->d_records, domain, 300);
4518 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4519 addRRSIG(keys, res->d_records, domain, 300);
4520 }
4521 else {
4522 setLWResult(res, 0, false, false, true);
4523 addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4524 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
4525 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4526 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4527 }
2b984251
RG
4528 return 1;
4529 }
4530 else if (ip == ComboAddress("192.0.2.2:53")) {
4531 setLWResult(res, 0, true, false, true);
f24465e5
RG
4532 if (type == QType::NS) {
4533 if (domain == DNSName("powerdns.com.")) {
4534 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4535 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4536 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4537 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4538 }
4539 else {
4540 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4541 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4542 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A, QType::NSEC, QType::RRSIG }, 600, res->d_records);
4543 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4544 }
4545 }
4546 else {
4547 addRecordToLW(res, domain, QType::A, "192.0.2.42");
4548 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300, false, boost::none, DNSName("*.powerdns.com"));
4549 addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A, QType::NSEC, QType::RRSIG }, 600, res->d_records);
4550 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4551 }
2b984251
RG
4552 return 1;
4553 }
4554 }
4555
4556 return 0;
4557 });
4558
4559 vector<DNSRecord> ret;
4560 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4561 BOOST_CHECK_EQUAL(res, RCode::NoError);
4562 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
4563 BOOST_REQUIRE_EQUAL(ret.size(), 4);
f24465e5 4564 BOOST_CHECK_EQUAL(queriesCount, 9);
2b984251
RG
4565
4566 /* again, to test the cache */
4567 ret.clear();
4568 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4569 BOOST_CHECK_EQUAL(res, RCode::NoError);
4570 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
4571 BOOST_REQUIRE_EQUAL(ret.size(), 4);
f24465e5 4572 BOOST_CHECK_EQUAL(queriesCount, 9);
2b984251
RG
4573}
4574
a53e8fe3
RG
4575BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure) {
4576 std::unique_ptr<SyncRes> sr;
4577 initSR(sr, true);
4578
4579 g_dnssecmode = DNSSECMode::ValidateAll;
4580
4581 primeHints();
4582 const DNSName target("www.powerdns.com.");
4583 testkeysset_t keys;
4584
4585 auto luaconfsCopy = g_luaconfs.getCopy();
4586 luaconfsCopy.dsAnchors.clear();
4587 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4588 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4589 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4590
4591 g_luaconfs.setState(luaconfsCopy);
4592
4593 size_t queriesCount = 0;
4594 size_t dsQueriesCount = 0;
4595
4596 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) {
4597 queriesCount++;
4598
4599 if (type == QType::DS) {
4600 DNSName auth(domain);
4601 auth.chopOff();
4602 dsQueriesCount++;
4603
4604 setLWResult(res, 0, true, false, true);
4605 addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
4606 addRRSIG(keys, res->d_records, auth, 300);
4607 return 1;
4608 }
4609 else if (type == QType::DNSKEY) {
4610 setLWResult(res, 0, true, false, true);
4611 addDNSKEY(keys, domain, 300, res->d_records);
4612 addRRSIG(keys, res->d_records, domain, 300);
4613 return 1;
4614 }
f24465e5 4615 else {
a53e8fe3
RG
4616 if (isRootServer(ip)) {
4617 setLWResult(res, 0, false, false, true);
4618 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4619 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4620 /* No DS on referral, and no denial of the DS either */
4621 return 1;
4622 }
4623 else if (ip == ComboAddress("192.0.2.1:53")) {
f24465e5
RG
4624 if (domain == DNSName("com.")) {
4625 setLWResult(res, 0, true, false, true);
4626 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
4627 addRRSIG(keys, res->d_records, domain, 300);
4628 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4629 addRRSIG(keys, res->d_records, domain, 300);
4630 }
4631 else {
4632 setLWResult(res, 0, false, false, true);
4633 addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4634 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4635 /* No DS on referral, and no denial of the DS either */
4636 }
a53e8fe3
RG
4637 return 1;
4638 }
4639 else if (ip == ComboAddress("192.0.2.2:53")) {
4640 setLWResult(res, 0, true, false, true);
f24465e5
RG
4641 if (type == QType::NS) {
4642 if (domain == DNSName("powerdns.com.")) {
4643 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4644 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4645 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4646 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4647 }
4648 else {
4649 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4650 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4651 addNSECRecordToLW(DNSName("www.powerdns.com."), DNSName("wwz.powerdns.com."), { QType::A, QType::NSEC, QType::RRSIG }, 600, res->d_records);
4652 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4653 }
4654 }
4655 else {
4656 addRecordToLW(res, domain, QType::A, "192.0.2.42");
4657 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
4658 }
4659
a53e8fe3
RG
4660 return 1;
4661 }
4662 }
4663
4664 return 0;
4665 });
4666
4667 vector<DNSRecord> ret;
4668 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4669 BOOST_CHECK_EQUAL(res, RCode::NoError);
4670 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
f24465e5
RG
4671 BOOST_REQUIRE_EQUAL(ret.size(), 2);
4672 BOOST_CHECK_EQUAL(queriesCount, 11);
a53e8fe3
RG
4673 BOOST_CHECK_EQUAL(dsQueriesCount, 2);
4674
4675 /* again, to test the cache */
4676 ret.clear();
4677 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4678 BOOST_CHECK_EQUAL(res, RCode::NoError);
4679 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
f24465e5
RG
4680 BOOST_REQUIRE_EQUAL(ret.size(), 2);
4681 BOOST_CHECK_EQUAL(queriesCount, 11);
a53e8fe3
RG
4682 BOOST_CHECK_EQUAL(dsQueriesCount, 2);
4683}
4684
4685BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure) {
4686 std::unique_ptr<SyncRes> sr;
f24465e5 4687 initSR(sr, true);
a53e8fe3
RG
4688
4689 g_dnssecmode = DNSSECMode::ValidateAll;
4690
4691 primeHints();
4692 const DNSName target("www.powerdns.com.");
4693 testkeysset_t keys;
4694
4695 auto luaconfsCopy = g_luaconfs.getCopy();
4696 luaconfsCopy.dsAnchors.clear();
4697 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4698 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4699
4700 g_luaconfs.setState(luaconfsCopy);
4701
4702 size_t queriesCount = 0;
4703 size_t dsQueriesCount = 0;
4704
4705 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) {
4706 queriesCount++;
4707
4708 if (type == QType::DS) {
4709 DNSName auth(domain);
4710 auth.chopOff();
4711 dsQueriesCount++;
4712
4713 setLWResult(res, 0, true, false, true);
4714 if (domain == DNSName("com.")) {
4715 addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
4716 }
4717 else {
f24465e5
RG
4718 addRecordToLW(res, "com.", QType::SOA, "a.gtld-servers.com. hostmastercom. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4719 addRRSIG(keys, res->d_records, DNSName("com."), 300);
a53e8fe3
RG
4720 addNSECRecordToLW(domain, DNSName("powerdnt.com."), { QType::NS }, 600, res->d_records);
4721 }
4722 addRRSIG(keys, res->d_records, auth, 300);
4723 return 1;
4724 }
4725 else if (type == QType::DNSKEY) {
4726 setLWResult(res, 0, true, false, true);
4727 addDNSKEY(keys, domain, 300, res->d_records);
4728 addRRSIG(keys, res->d_records, domain, 300);
4729 return 1;
4730 }
a69867f2 4731 else {
a53e8fe3
RG
4732 if (isRootServer(ip)) {
4733 setLWResult(res, 0, false, false, true);
4734 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4735 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4736 /* No DS on referral, and no denial of the DS either */
4737 return 1;
4738 }
4739 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
4740 if (domain == DNSName("com.")) {
4741 setLWResult(res, 0, true, false, true);
4742 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
f24465e5 4743 addRRSIG(keys, res->d_records, domain, 300);
a69867f2 4744 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
f24465e5 4745 addRRSIG(keys, res->d_records, domain, 300);
a69867f2
RG
4746 }
4747 else {
4748 setLWResult(res, 0, false, false, true);
4749 addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4750 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4751 /* No DS on referral, and no denial of the DS either */
4752 }
a53e8fe3
RG
4753 return 1;
4754 }
4755 else if (ip == ComboAddress("192.0.2.2:53")) {
4756 setLWResult(res, 0, true, false, true);
f24465e5
RG
4757 if (type == QType::NS) {
4758 if (domain == DNSName("powerdns.com.")) {
4759 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4760 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4761 }
4762 else {
4763 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4764 }
4765 }
4766 else {
4767 addRecordToLW(res, domain, QType::A, "192.0.2.42");
4768 }
a53e8fe3
RG
4769 return 1;
4770 }
4771 }
4772
4773 return 0;
4774 });
4775
4776 vector<DNSRecord> ret;
4777 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4778 BOOST_CHECK_EQUAL(res, RCode::NoError);
4779 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
4780 BOOST_REQUIRE_EQUAL(ret.size(), 1);
f24465e5 4781 BOOST_CHECK_EQUAL(queriesCount, 10);
a53e8fe3
RG
4782 BOOST_CHECK_EQUAL(dsQueriesCount, 2);
4783
4784 /* again, to test the cache */
4785 ret.clear();
4786 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4787 BOOST_CHECK_EQUAL(res, RCode::NoError);
4788 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
4789 BOOST_REQUIRE_EQUAL(ret.size(), 1);
f24465e5 4790 BOOST_CHECK_EQUAL(queriesCount, 10);
a53e8fe3
RG
4791 BOOST_CHECK_EQUAL(dsQueriesCount, 2);
4792}
4793
e59c8907 4794BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec) {
b7f378d1 4795 std::unique_ptr<SyncRes> sr;
895449a5 4796 initSR(sr, true);
b7f378d1
RG
4797
4798 g_dnssecmode = DNSSECMode::ValidateAll;
4799
4800 primeHints();
4801 const DNSName target("powerdns.com.");
4802 testkeysset_t keys;
4803
4804 auto luaconfsCopy = g_luaconfs.getCopy();
4805 luaconfsCopy.dsAnchors.clear();
4806 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4807 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4808 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4809
4810 g_luaconfs.setState(luaconfsCopy);
4811
4812 size_t queriesCount = 0;
4813
4814 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) {
4815 queriesCount++;
4816
4817 if (type == QType::DS) {
a53e8fe3 4818 return 0;
b7f378d1
RG
4819 }
4820 else if (type == QType::DNSKEY) {
4821 setLWResult(res, 0, true, false, true);
4822 addDNSKEY(keys, domain, 300, res->d_records);
4823 addRRSIG(keys, res->d_records, domain, 300);
4824 return 1;
4825 }
a69867f2 4826 else {
b7f378d1
RG
4827 if (isRootServer(ip)) {
4828 setLWResult(res, 0, false, false, true);
4829 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4830 addDS(DNSName("com."), 300, res->d_records, keys);
4831 addRRSIG(keys, res->d_records, DNSName("."), 300);
4832 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4833 return 1;
4834 }
4835 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
4836 if (domain == DNSName("com.")) {
4837 setLWResult(res, 0, true, false, true);
4838 addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
4839 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4840 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4841 }
4842 else {
4843 setLWResult(res, 0, false, false, true);
4844 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4845 addDS(domain, 300, res->d_records, keys);
4846 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4847 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4848 }
b7f378d1
RG
4849 return 1;
4850 }
4851 else if (ip == ComboAddress("192.0.2.2:53")) {
4852 setLWResult(res, 0, true, false, true);
a69867f2
RG
4853 if (type == QType::NS) {
4854 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4855 addRRSIG(keys, res->d_records, domain, 300);
4856 }
4857 else {
4858 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4859 addRRSIG(keys, res->d_records, domain, 300);
4860 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS, QType::DNSKEY }, 600, res->d_records);
4861 /* NO RRSIG for the NSEC record! */
4862 }
b7f378d1
RG
4863 return 1;
4864 }
4865 }
4866
4867 return 0;
4868 });
4869
4870 /* NSEC record without the corresponding RRSIG in a secure zone, should be Bogus! */
4871 vector<DNSRecord> ret;
4872 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4873 BOOST_CHECK_EQUAL(res, RCode::NoError);
4874 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
4875 BOOST_CHECK_EQUAL(ret.size(), 3);
a69867f2 4876 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4877
4878 /* again, to test the cache */
4879 ret.clear();
4880 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4881 BOOST_CHECK_EQUAL(res, RCode::NoError);
4882 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
4883 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 4884 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4885}
4886
e59c8907 4887BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec) {
b7f378d1 4888 std::unique_ptr<SyncRes> sr;
895449a5 4889 initSR(sr, true);
b7f378d1
RG
4890
4891 g_dnssecmode = DNSSECMode::ValidateAll;
4892
4893 primeHints();
4894 const DNSName target("powerdns.com.");
4895 testkeysset_t keys;
4896
4897 auto luaconfsCopy = g_luaconfs.getCopy();
4898 luaconfsCopy.dsAnchors.clear();
4899 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4900 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4901 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4902
4903 g_luaconfs.setState(luaconfsCopy);
4904
4905 size_t queriesCount = 0;
4906
4907 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) {
4908 queriesCount++;
4909
4910 if (type == QType::DS) {
a53e8fe3 4911 return 0;
b7f378d1
RG
4912 }
4913 else if (type == QType::DNSKEY) {
4914 setLWResult(res, 0, true, false, true);
4915 addDNSKEY(keys, domain, 300, res->d_records);
4916 addRRSIG(keys, res->d_records, domain, 300);
4917 return 1;
4918 }
a69867f2 4919 else {
b7f378d1
RG
4920 if (isRootServer(ip)) {
4921 setLWResult(res, 0, false, false, true);
4922 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
4923 addDS(DNSName("com."), 300, res->d_records, keys);
4924 addRRSIG(keys, res->d_records, DNSName("."), 300);
4925 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4926 return 1;
4927 }
4928 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
4929 if (domain == DNSName("com.")) {
4930 setLWResult(res, 0, true, false, true);
4931 addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
4932 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4933 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
4934 }
4935 else {
4936 setLWResult(res, 0, false, false, true);
4937 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
4938 addDS(domain, 300, res->d_records, keys);
4939 addRRSIG(keys, res->d_records, DNSName("com."), 300);
4940 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
4941 }
b7f378d1
RG
4942 return 1;
4943 }
4944 else if (ip == ComboAddress("192.0.2.2:53")) {
4945 setLWResult(res, 0, true, false, true);
a69867f2
RG
4946 if (type == QType::NS) {
4947 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
4948 addRRSIG(keys, res->d_records, domain, 300);
4949 }
4950 else {
4951 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
4952 addRRSIG(keys, res->d_records, domain, 300);
b7f378d1 4953
a69867f2
RG
4954 /* NO NSEC record! */
4955 }
b7f378d1
RG
4956 return 1;
4957 }
4958 }
4959
4960 return 0;
4961 });
4962
4963 /* no NSEC record in a secure zone, should be Bogus! */
4964 vector<DNSRecord> ret;
4965 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4966 BOOST_CHECK_EQUAL(res, RCode::NoError);
4967 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
4968 BOOST_CHECK_EQUAL(ret.size(), 2);
a69867f2 4969 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4970
4971 /* again, to test the cache */
4972 ret.clear();
4973 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
4974 BOOST_CHECK_EQUAL(res, RCode::NoError);
4975 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
4976 BOOST_REQUIRE_EQUAL(ret.size(), 2);
a69867f2 4977 BOOST_CHECK_EQUAL(queriesCount, 8);
b7f378d1
RG
4978}
4979
4980BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure) {
4981 std::unique_ptr<SyncRes> sr;
895449a5 4982 initSR(sr, true);
b7f378d1
RG
4983
4984 g_dnssecmode = DNSSECMode::ValidateAll;
4985
4986 primeHints();
4987 const DNSName target("powerdns.com.");
4988 const ComboAddress targetAddr("192.0.2.42");
4989 testkeysset_t keys;
4990
4991 auto luaconfsCopy = g_luaconfs.getCopy();
4992 luaconfsCopy.dsAnchors.clear();
4993 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
4994 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
4995
4996 g_luaconfs.setState(luaconfsCopy);
4997
4998 size_t queriesCount = 0;
4999
5000 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) {
5001 queriesCount++;
5002
5003 if (type == QType::DS) {
a53e8fe3 5004 if (domain == target) {
b7f378d1 5005 setLWResult(res, 0, false, false, true);
895449a5 5006 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
b7f378d1
RG
5007 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
5008 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5009 return 1;
5010 }
5011 }
5012 else if (type == QType::DNSKEY) {
5013 if (domain == g_rootdnsname || domain == DNSName("com.")) {
5014 setLWResult(res, 0, true, false, true);
5015 addDNSKEY(keys, domain, 300, res->d_records);
5016 addRRSIG(keys, res->d_records, domain, 300);
5017 return 1;
5018 }
5019 else {
5020 setLWResult(res, 0, false, false, true);
895449a5 5021 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
b7f378d1
RG
5022 return 1;
5023 }
5024 }
a69867f2 5025 else {
b7f378d1
RG
5026 if (isRootServer(ip)) {
5027 setLWResult(res, 0, false, false, true);
5028 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5029 addDS(DNSName("com."), 300, res->d_records, keys);
5030 addRRSIG(keys, res->d_records, DNSName("."), 300);
5031 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5032 return 1;
5033 }
5034 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
5035 if (domain == DNSName("com.")) {
5036 setLWResult(res, 0, true, false, true);
5037 addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
5038 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5039 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5040 }
5041 else {
5042 setLWResult(res, 0, false, false, true);
5043 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5044 /* no DS */
5045 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
5046 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5047 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5048 }
b7f378d1
RG
5049 return 1;
5050 }
5051 else if (ip == ComboAddress("192.0.2.2:53")) {
5052 setLWResult(res, 0, true, false, true);
a69867f2
RG
5053 if (type == QType::NS) {
5054 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5055 }
5056 else {
5057 addRecordToLW(res, domain, QType::A, targetAddr.toString());
5058 }
b7f378d1
RG
5059 return 1;
5060 }
5061 }
5062
5063 return 0;
5064 });
5065
5066 vector<DNSRecord> ret;
5067 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5068 BOOST_CHECK_EQUAL(res, RCode::NoError);
5069 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5070 BOOST_REQUIRE_EQUAL(ret.size(), 1);
5071 BOOST_CHECK(ret[0].d_type == QType::A);
a69867f2
RG
5072 /* 4 NS: com at ., com at com, powerdns.com at com, powerdns.com at powerdns.com
5073 4 DNSKEY: ., com (not for powerdns.com because DS denial in referral)
5074 1 query for A */
5075 BOOST_CHECK_EQUAL(queriesCount, 7);
b7f378d1
RG
5076
5077 /* again, to test the cache */
5078 ret.clear();
5079 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5080 BOOST_CHECK_EQUAL(res, RCode::NoError);
5081 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5082 BOOST_REQUIRE_EQUAL(ret.size(), 1);
5083 BOOST_CHECK(ret[0].d_type == QType::A);
a69867f2 5084 BOOST_CHECK_EQUAL(queriesCount, 7);
b7f378d1
RG
5085}
5086
70b3fe7a
RG
5087BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut) {
5088 std::unique_ptr<SyncRes> sr;
a69867f2 5089 initSR(sr, true);
70b3fe7a
RG
5090
5091 g_dnssecmode = DNSSECMode::ValidateAll;
5092
5093 primeHints();
5094 const DNSName target("www.sub.powerdns.com.");
5095 const ComboAddress targetAddr("192.0.2.42");
5096 testkeysset_t keys;
5097
5098 auto luaconfsCopy = g_luaconfs.getCopy();
5099 luaconfsCopy.dsAnchors.clear();
5100 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5101 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5102 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5103
5104 g_luaconfs.setState(luaconfsCopy);
5105
5106 size_t queriesCount = 0;
5107
5108 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) {
5109 queriesCount++;
5110
5111 if (type == QType::DS) {
5112 if (domain == DNSName("sub.powerdns.com.")) {
5113 setLWResult(res, 0, false, false, true);
5114 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5115 addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
5116 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
5117 addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
5118 return 1;
5119 }
5120 else if (domain == DNSName("www.sub.powerdns.com.")) {
5121 setLWResult(res, 0, false, false, true);
5122 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);
5123 return 1;
5124 }
5125 }
5126 else if (type == QType::DNSKEY) {
a69867f2 5127 if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
70b3fe7a
RG
5128 setLWResult(res, 0, true, false, true);
5129 addDNSKEY(keys, domain, 300, res->d_records);
5130 addRRSIG(keys, res->d_records, domain, 300);
5131 return 1;
5132 }
5133 else {
5134 setLWResult(res, 0, false, false, true);
5135 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5136 return 1;
5137 }
5138 }
88cb0fe0 5139 else {
70b3fe7a
RG
5140 if (isRootServer(ip)) {
5141 setLWResult(res, 0, false, false, true);
5142 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5143 addDS(DNSName("com."), 300, res->d_records, keys);
5144 addRRSIG(keys, res->d_records, DNSName("."), 300);
5145 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5146 return 1;
5147 }
5148 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
5149 if (domain == DNSName("com.")) {
5150 setLWResult(res, 0, true, false, true);
5151 addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
5152 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5153 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5154 }
5155 else {
5156 setLWResult(res, 0, false, false, true);
5157 addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5158 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
5159 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5160 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5161 }
70b3fe7a
RG
5162 return 1;
5163 }
5164 else if (ip == ComboAddress("192.0.2.2:53")) {
5165 setLWResult(res, 0, true, false, true);
a69867f2
RG
5166 if (type == QType::NS) {
5167 if (domain == DNSName("www.sub.powerdns.com.")) {
5168 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);
5169 }
5170 else if (domain == DNSName("sub.powerdns.com.")) {
5171 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5172 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
5173 addNSECRecordToLW(domain, DNSName("tub.powerdns.com."), { QType::NS }, 600, res->d_records);
5174 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
5175 }
5176 else if (domain == DNSName("powerdns.com.")) {
5177 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5178 addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
5179 }
5180 } else {
5181 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
5182 }
70b3fe7a
RG
5183 return 1;
5184 }
5185 }
5186
5187 return 0;
5188 });
5189
5190 vector<DNSRecord> ret;
5191 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5192 BOOST_CHECK_EQUAL(res, RCode::NoError);
5193 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5194 BOOST_REQUIRE_EQUAL(ret.size(), 1);
5195 BOOST_CHECK(ret[0].d_type == QType::A);
a69867f2 5196 BOOST_CHECK_EQUAL(queriesCount, 11);
70b3fe7a
RG
5197
5198 /* again, to test the cache */
5199 ret.clear();
5200 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5201 BOOST_CHECK_EQUAL(res, RCode::NoError);
5202 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5203 BOOST_REQUIRE_EQUAL(ret.size(), 1);
5204 BOOST_CHECK(ret[0].d_type == QType::A);
a69867f2 5205 BOOST_CHECK_EQUAL(queriesCount, 11);
70b3fe7a
RG
5206}
5207
5208BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut) {
5209 std::unique_ptr<SyncRes> sr;
a69867f2 5210 initSR(sr, true);
70b3fe7a
RG
5211
5212 g_dnssecmode = DNSSECMode::ValidateAll;
5213
5214 primeHints();
5215 const DNSName target("www.sub.powerdns.com.");
5216 const ComboAddress targetAddr("192.0.2.42");
5217 testkeysset_t keys;
5218
5219 auto luaconfsCopy = g_luaconfs.getCopy();
5220 luaconfsCopy.dsAnchors.clear();
5221 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5222 /* No key material for .com */
5223 /* But TA for sub.powerdns.com. */
5224 generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5225 luaconfsCopy.dsAnchors[DNSName("sub.powerdns.com.")].insert(keys[DNSName("sub.powerdns.com.")].second);
5226 g_luaconfs.setState(luaconfsCopy);
5227
5228 size_t queriesCount = 0;
5229
5230 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) {
5231 queriesCount++;
5232
5233 if (type == QType::DS) {
88cb0fe0
RG
5234 if (domain == DNSName("www.sub.powerdns.com")) {
5235 setLWResult(res, 0, false, false, true);
5236 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);
5237 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
5238 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A }, 600, res->d_records);
5239 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
5240 }
5241 else {
5242 setLWResult(res, 0, false, false, true);
5243 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5244 }
70b3fe7a
RG
5245 return 1;
5246 }
5247 else if (type == QType::DNSKEY) {
5248 if (domain == g_rootdnsname || domain == DNSName("sub.powerdns.com.")) {
5249 setLWResult(res, 0, true, false, true);
5250 addDNSKEY(keys, domain, 300, res->d_records);
5251 addRRSIG(keys, res->d_records, domain, 300);
5252 return 1;
5253 }
5254 }
88cb0fe0 5255 else {
70b3fe7a
RG
5256 if (isRootServer(ip)) {
5257 setLWResult(res, 0, false, false, true);
5258 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5259 /* no DS */
5260 addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS }, 600, res->d_records);
5261 addRRSIG(keys, res->d_records, DNSName("."), 300);
5262 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5263 return 1;
5264 }
5265 else if (ip == ComboAddress("192.0.2.1:53")) {
88cb0fe0
RG
5266 if (domain == DNSName("com.")) {
5267 setLWResult(res, 0, true, false, true);
5268 addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com.");
5269 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5270 }
5271 else if (domain == DNSName("powerdns.com.")) {
5272 setLWResult(res, 0, false, false, true);
5273 addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5274 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5275 }
70b3fe7a
RG
5276 return 1;
5277 }
5278 else if (ip == ComboAddress("192.0.2.2:53")) {
5279 setLWResult(res, 0, true, false, true);
88cb0fe0
RG
5280 if (type == QType::NS) {
5281 if (domain == DNSName("www.sub.powerdns.com.")) {
5282 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);
5283 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
5284 addNSECRecordToLW(DNSName("www.sub.powerdns.com"), DNSName("vww.sub.powerdns.com."), { QType::A }, 600, res->d_records);
5285 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com"), 300);
5286 }
5287 else if (domain == DNSName("sub.powerdns.com.")) {
5288 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5289 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com."), 300);
5290 }
5291 else if (domain == DNSName("powerdns.com.")) {
5292 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5293 }
5294 }
5295 else if (domain == DNSName("www.sub.powerdns.com.")) {
5296 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
5297 addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com."), 300);
5298 }
70b3fe7a
RG
5299 return 1;
5300 }
5301 }
5302
5303 return 0;
5304 });
5305
5306 vector<DNSRecord> ret;
5307 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5308 BOOST_CHECK_EQUAL(res, RCode::NoError);
5309 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
88cb0fe0 5310 BOOST_REQUIRE_EQUAL(ret.size(), 2);
70b3fe7a 5311 BOOST_CHECK(ret[0].d_type == QType::A);
a69867f2 5312 BOOST_CHECK_EQUAL(queriesCount, 9);
70b3fe7a
RG
5313
5314 /* again, to test the cache */
5315 ret.clear();
5316 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5317 BOOST_CHECK_EQUAL(res, RCode::NoError);
5318 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
88cb0fe0 5319 BOOST_REQUIRE_EQUAL(ret.size(), 2);
70b3fe7a 5320 BOOST_CHECK(ret[0].d_type == QType::A);
a69867f2 5321 BOOST_CHECK_EQUAL(queriesCount, 9);
70b3fe7a
RG
5322}
5323
b7f378d1
RG
5324BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata) {
5325 std::unique_ptr<SyncRes> sr;
895449a5 5326 initSR(sr, true);
b7f378d1
RG
5327
5328 g_dnssecmode = DNSSECMode::ValidateAll;
5329
5330 primeHints();
5331 const DNSName target("powerdns.com.");
5332 testkeysset_t keys;
5333
5334 auto luaconfsCopy = g_luaconfs.getCopy();
5335 luaconfsCopy.dsAnchors.clear();
5336 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5337 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5338
5339 g_luaconfs.setState(luaconfsCopy);
5340
5341 size_t queriesCount = 0;
5342
5343 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) {
5344 queriesCount++;
5345
5346 if (type == QType::DS) {
a53e8fe3 5347 if (domain == target) {
b7f378d1 5348 setLWResult(res, 0, false, false, true);
895449a5 5349 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
b7f378d1
RG
5350 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
5351 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5352 return 1;
5353 }
5354 }
5355 else if (type == QType::DNSKEY) {
5356 if (domain == g_rootdnsname || domain == DNSName("com.")) {
5357 setLWResult(res, 0, true, false, true);
5358 addDNSKEY(keys, domain, 300, res->d_records);
5359 addRRSIG(keys, res->d_records, domain, 300);
5360 return 1;
5361 }
5362 else {
5363 setLWResult(res, 0, false, false, true);
895449a5 5364 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
b7f378d1
RG
5365 return 1;
5366 }
5367 }
a69867f2 5368 else {
b7f378d1
RG
5369 if (isRootServer(ip)) {
5370 setLWResult(res, 0, false, false, true);
5371 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5372 addDS(DNSName("com."), 300, res->d_records, keys);
5373 addRRSIG(keys, res->d_records, DNSName("."), 300);
5374 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5375 return 1;
5376 }
5377 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
5378 if (domain == DNSName("com.")) {
5379 setLWResult(res, 0, true, false, true);
5380 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
5381 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5382 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5383 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5384 }
5385 else {
5386 setLWResult(res, 0, false, false, true);
5387 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5388 /* no DS */
5389 addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
5390 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5391 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5392 }
b7f378d1
RG
5393 return 1;
5394 }
5395 else if (ip == ComboAddress("192.0.2.2:53")) {
a69867f2
RG
5396 if (type == QType::NS) {
5397 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5398 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5399 }
5400 else {
5401 setLWResult(res, 0, true, false, true);
5402 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5403 }
b7f378d1
RG
5404 return 1;
5405 }
5406 }
5407
5408 return 0;
5409 });
5410
5411 vector<DNSRecord> ret;
5412 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5413 BOOST_CHECK_EQUAL(res, RCode::NoError);
5414 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5415 BOOST_REQUIRE_EQUAL(ret.size(), 1);
a69867f2
RG
5416 /* 4 NS (com from root, com from com, powerdns.com from com,
5417 powerdns.com from powerdns.com)
5418 2 DNSKEY (. and com., none for powerdns.com because no DS)
5419 1 query for A
5420 */
5421 BOOST_CHECK_EQUAL(queriesCount, 7);
b7f378d1
RG
5422
5423 /* again, to test the cache */
5424 ret.clear();
5425 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5426 BOOST_CHECK_EQUAL(res, RCode::NoError);
5427 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5428 BOOST_REQUIRE_EQUAL(ret.size(), 1);
a69867f2 5429 BOOST_CHECK_EQUAL(queriesCount, 7);
b7f378d1
RG
5430}
5431
895449a5 5432BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname) {
b7f378d1 5433 std::unique_ptr<SyncRes> sr;
860d5e8e 5434 initSR(sr, true);
b7f378d1
RG
5435
5436 g_dnssecmode = DNSSECMode::ValidateAll;
5437
895449a5
RG
5438 primeHints();
5439 const DNSName target("powerdns.com.");
5440 const DNSName targetCName("power-dns.com.");
5441 const ComboAddress targetCNameAddr("192.0.2.42");
5442 testkeysset_t keys;
5443
5444 auto luaconfsCopy = g_luaconfs.getCopy();
5445 luaconfsCopy.dsAnchors.clear();
5446 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5447 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5448 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5449 g_luaconfs.setState(luaconfsCopy);
5450
5451 size_t queriesCount = 0;
5452
5453 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) {
5454 queriesCount++;
5455
5456 if (type == QType::DS) {
a53e8fe3 5457 if (domain == target) {
895449a5
RG
5458 setLWResult(res, 0, false, false, true);
5459 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5460 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), { QType::NS }, 600, res->d_records);
5461 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5462 return 1;
5463 }
5464 }
5465 else if (type == QType::DNSKEY) {
5466 if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
5467 setLWResult(res, 0, true, false, true);
5468 addDNSKEY(keys, domain, 300, res->d_records);
5469 addRRSIG(keys, res->d_records, domain, 300);
5470 return 1;
5471 }
5472 else {
5473 setLWResult(res, 0, false, false, true);
5474 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5475 return 1;
5476 }
5477 }
5478 else {
5479 if (isRootServer(ip)) {
5480 setLWResult(res, 0, false, false, true);
5481 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5482 addDS(DNSName("com."), 300, res->d_records, keys);
5483 addRRSIG(keys, res->d_records, DNSName("."), 300);
5484 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5485 return 1;
5486 }
5487 else if (ip == ComboAddress("192.0.2.1:53")) {
5488 setLWResult(res, 0, false, false, true);
a69867f2
RG
5489 if (domain == DNSName("com.")) {
5490 setLWResult(res, 0, true, false, true);
5491 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
5492 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5493 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5494 addRRSIG(keys, res->d_records, DNSName("com."), 300);
895449a5 5495 }
a69867f2
RG
5496 else {
5497 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5498 if (domain == DNSName("powerdns.com.")) {
5499 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
5500 }
5501 else if (domain == targetCName) {
5502 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), { QType::NS }, 600, res->d_records);
5503 }
5504 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5505 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
895449a5 5506 }
a69867f2 5507
895449a5
RG
5508 return 1;
5509 }
5510 else if (ip == ComboAddress("192.0.2.2:53")) {
5511 setLWResult(res, 0, true, false, true);
a69867f2
RG
5512
5513 if (type == QType::NS) {
5514 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5515 if (domain == DNSName("powerdns.com.")) {
5516 addRRSIG(keys, res->d_records, domain, 300);
5517 }
5518 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5519 if (domain == DNSName("powerdns.com.")) {
5520 addRRSIG(keys, res->d_records, domain, 300);
5521 }
895449a5 5522 }
a69867f2
RG
5523 else {
5524 if (domain == DNSName("powerdns.com.")) {
5525 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
5526 addRRSIG(keys, res->d_records, domain, 300);
5527 }
5528 else if (domain == targetCName) {
5529 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
5530 }
895449a5 5531 }
a69867f2 5532
895449a5
RG
5533 return 1;
5534 }
5535 }
5536
5537 return 0;
5538 });
5539
5540 vector<DNSRecord> ret;
5541 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5542 BOOST_CHECK_EQUAL(res, RCode::NoError);
5543 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5544 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5545 BOOST_CHECK_EQUAL(queriesCount, 11);
895449a5
RG
5546
5547 /* again, to test the cache */
5548 ret.clear();
5549 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5550 BOOST_CHECK_EQUAL(res, RCode::NoError);
5551 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5552 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5553 BOOST_CHECK_EQUAL(queriesCount, 11);
895449a5
RG
5554}
5555
3d5ebf10
RG
5556BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname) {
5557 std::unique_ptr<SyncRes> sr;
5558 initSR(sr, true);
5559
5560 g_dnssecmode = DNSSECMode::ValidateAll;
5561
5562 primeHints();
5563 const DNSName target("power-dns.com.");
5564 const DNSName targetCName("powerdns.com.");
5565 const ComboAddress targetCNameAddr("192.0.2.42");
5566 testkeysset_t keys;
5567
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);
5573 g_luaconfs.setState(luaconfsCopy);
5574
5575 size_t queriesCount = 0;
5576
5577 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) {
5578 queriesCount++;
5579
5580 if (type == QType::DS) {
a53e8fe3 5581 if (domain == DNSName("power-dns.com.")) {
3d5ebf10
RG
5582 setLWResult(res, 0, false, false, true);
5583 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5584 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), { QType::NS }, 600, res->d_records);
5585 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5586 return 1;
5587 }
5588 }
5589 else if (type == QType::DNSKEY) {
5590 if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
5591 setLWResult(res, 0, true, false, true);
5592 addDNSKEY(keys, domain, 300, res->d_records);
5593 addRRSIG(keys, res->d_records, domain, 300);
5594 return 1;
5595 }
5596 else {
5597 setLWResult(res, 0, false, false, true);
5598 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
5599 return 1;
5600 }
5601 }
5602 else {
5603 if (isRootServer(ip)) {
5604 setLWResult(res, 0, false, false, true);
5605 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5606 addDS(DNSName("com."), 300, res->d_records, keys);
5607 addRRSIG(keys, res->d_records, DNSName("."), 300);
5608 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5609 return 1;
5610 }
5611 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
5612 if (domain == DNSName("com.")) {
5613 setLWResult(res, 0, true, false, true);
5614 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
5615 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5616 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5617 addRRSIG(keys, res->d_records, DNSName("com."), 300);
3d5ebf10 5618 }
a69867f2
RG
5619 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
5620 setLWResult(res, 0, false, false, true);
5621 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5622 if (domain == targetCName) {
5623 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
5624 }
5625 else if (domain == target) {
5626 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), { QType::NS }, 600, res->d_records);
5627 }
5628 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5629 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
3d5ebf10 5630 }
3d5ebf10
RG
5631 return 1;
5632 }
5633 else if (ip == ComboAddress("192.0.2.2:53")) {
5634 setLWResult(res, 0, true, false, true);
a69867f2
RG
5635 if (type == QType::NS) {
5636 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5637 if (domain == DNSName("powerdns.com.")) {
5638 addRRSIG(keys, res->d_records, domain, 300);
5639 }
5640 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5641 if (domain == DNSName("powerdns.com.")) {
5642 addRRSIG(keys, res->d_records, domain, 300);
5643 }
3d5ebf10 5644 }
a69867f2
RG
5645 else {
5646 if (domain == target) {
5647 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
5648 }
5649 else if (domain == targetCName) {
5650 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
5651 addRRSIG(keys, res->d_records, domain, 300);
5652 }
3d5ebf10
RG
5653 }
5654 return 1;
5655 }
5656 }
5657
5658 return 0;
5659 });
5660
5661 vector<DNSRecord> ret;
5662 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5663 BOOST_CHECK_EQUAL(res, RCode::NoError);
5664 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5665 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5666 BOOST_CHECK_EQUAL(queriesCount, 11);
3d5ebf10
RG
5667
5668 /* again, to test the cache */
5669 ret.clear();
5670 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5671 BOOST_CHECK_EQUAL(res, RCode::NoError);
5672 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
5673 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5674 BOOST_CHECK_EQUAL(queriesCount, 11);
3d5ebf10
RG
5675}
5676
5677BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname) {
5678 std::unique_ptr<SyncRes> sr;
5679 initSR(sr, true);
5680
5681 g_dnssecmode = DNSSECMode::ValidateAll;
5682
5683 primeHints();
5684 const DNSName target("power-dns.com.");
5685 const DNSName targetCName("powerdns.com.");
5686 const ComboAddress targetCNameAddr("192.0.2.42");
5687 testkeysset_t keys;
5688
5689 auto luaconfsCopy = g_luaconfs.getCopy();
5690 luaconfsCopy.dsAnchors.clear();
5691 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5692 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5693 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5694 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5695 g_luaconfs.setState(luaconfsCopy);
5696
5697 size_t queriesCount = 0;
5698
5699 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) {
5700 queriesCount++;
5701
5702 if (type == QType::DS) {
a53e8fe3 5703 return 0;
3d5ebf10
RG
5704 }
5705 else if (type == QType::DNSKEY) {
5706 setLWResult(res, 0, true, false, true);
5707 addDNSKEY(keys, domain, 300, res->d_records);
5708 addRRSIG(keys, res->d_records, domain, 300);
5709 return 1;
5710 }
5711 else {
5712 if (isRootServer(ip)) {
5713 setLWResult(res, 0, false, false, true);
5714 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5715 addDS(DNSName("com."), 300, res->d_records, keys);
5716 addRRSIG(keys, res->d_records, DNSName("."), 300);
5717 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5718 return 1;
5719 }
5720 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
5721 if (domain == DNSName("com.")) {
5722 setLWResult(res, 0, true, false, true);
5723 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
5724 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5725 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5726 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5727 }
5728 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
5729 setLWResult(res, 0, false, false, true);
5730 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5731 addDS(DNSName(domain), 300, res->d_records, keys);
5732 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5733 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5734 }
3d5ebf10
RG
5735 return 1;
5736 }
5737 else if (ip == ComboAddress("192.0.2.2:53")) {
5738 setLWResult(res, 0, true, false, true);
a69867f2
RG
5739 if (type == QType::NS) {
5740 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5741 addRRSIG(keys, res->d_records, domain, 300);
5742 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
3d5ebf10
RG
5743 addRRSIG(keys, res->d_records, domain, 300);
5744 }
a69867f2
RG
5745 else {
5746 if (domain == target) {
5747 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
5748 /* No RRSIG, leading to bogus */
5749 }
5750 else if (domain == targetCName) {
5751 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
5752 addRRSIG(keys, res->d_records, domain, 300);
5753 }
5754 }
3d5ebf10
RG
5755 return 1;
5756 }
5757 }
5758
5759 return 0;
5760 });
5761
5762 vector<DNSRecord> ret;
5763 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5764 BOOST_CHECK_EQUAL(res, RCode::NoError);
5765 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
5766 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5767 BOOST_CHECK_EQUAL(queriesCount, 12);
3d5ebf10
RG
5768
5769 /* again, to test the cache */
5770 ret.clear();
5771 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5772 BOOST_CHECK_EQUAL(res, RCode::NoError);
5773 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
5774 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5775 BOOST_CHECK_EQUAL(queriesCount, 12);
3d5ebf10
RG
5776}
5777
5778BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname) {
5779 std::unique_ptr<SyncRes> sr;
5780 initSR(sr, true);
5781
5782 g_dnssecmode = DNSSECMode::ValidateAll;
5783
5784 primeHints();
5785 const DNSName target("power-dns.com.");
5786 const DNSName targetCName("powerdns.com.");
5787 const ComboAddress targetCNameAddr("192.0.2.42");
5788 testkeysset_t keys;
5789
5790 auto luaconfsCopy = g_luaconfs.getCopy();
5791 luaconfsCopy.dsAnchors.clear();
5792 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5793 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5794 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5795 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5796 g_luaconfs.setState(luaconfsCopy);
5797
5798 size_t queriesCount = 0;
5799
5800 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) {
5801 queriesCount++;
5802
5803 if (type == QType::DS) {
a53e8fe3 5804 return 0;
3d5ebf10
RG
5805 }
5806 else if (type == QType::DNSKEY) {
5807 setLWResult(res, 0, true, false, true);
5808 addDNSKEY(keys, domain, 300, res->d_records);
5809 addRRSIG(keys, res->d_records, domain, 300);
5810 return 1;
5811 }
5812 else {
5813 if (isRootServer(ip)) {
5814 setLWResult(res, 0, false, false, true);
5815 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5816 addDS(DNSName("com."), 300, res->d_records, keys);
5817 addRRSIG(keys, res->d_records, DNSName("."), 300);
5818 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5819 return 1;
5820 }
5821 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
5822 if (domain == DNSName("com.")) {
5823 setLWResult(res, 0, true, false, true);
5824 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
5825 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5826 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5827 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5828 }
5829 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
5830 setLWResult(res, 0, false, false, true);
5831 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5832 addDS(DNSName(domain), 300, res->d_records, keys);
5833 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5834 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5835 }
3d5ebf10
RG
5836 return 1;
5837 }
5838 else if (ip == ComboAddress("192.0.2.2:53")) {
5839 setLWResult(res, 0, true, false, true);
a69867f2
RG
5840 if (type == QType::NS) {
5841 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
5842 addRRSIG(keys, res->d_records, domain, 300);
5843 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
3d5ebf10
RG
5844 addRRSIG(keys, res->d_records, domain, 300);
5845 }
a69867f2
RG
5846 else {
5847 if (domain == target) {
5848 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
5849 addRRSIG(keys, res->d_records, domain, 300);
5850 }
5851 else if (domain == targetCName) {
5852 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
5853 /* No RRSIG, leading to bogus */
5854 }
3d5ebf10
RG
5855 }
5856 return 1;
5857 }
5858 }
5859
5860 return 0;
5861 });
5862
5863 vector<DNSRecord> ret;
5864 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5865 BOOST_CHECK_EQUAL(res, RCode::NoError);
5866 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
5867 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5868 BOOST_CHECK_EQUAL(queriesCount, 12);
3d5ebf10
RG
5869
5870 /* again, to test the cache */
5871 ret.clear();
5872 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5873 BOOST_CHECK_EQUAL(res, RCode::NoError);
5874 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
5875 BOOST_REQUIRE_EQUAL(ret.size(), 3);
a69867f2 5876 BOOST_CHECK_EQUAL(queriesCount, 12);
3d5ebf10
RG
5877}
5878
5879BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname) {
5880 std::unique_ptr<SyncRes> sr;
5881 initSR(sr, true);
5882
5883 g_dnssecmode = DNSSECMode::ValidateAll;
5884
5885 primeHints();
5886 const DNSName target("power-dns.com.");
5887 const DNSName targetCName("powerdns.com.");
5888 const ComboAddress targetCNameAddr("192.0.2.42");
5889 testkeysset_t keys;
5890
5891 auto luaconfsCopy = g_luaconfs.getCopy();
5892 luaconfsCopy.dsAnchors.clear();
5893 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5894 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5895 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5896 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5897 g_luaconfs.setState(luaconfsCopy);
5898
5899 size_t queriesCount = 0;
5900
5901 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) {
5902 queriesCount++;
5903
5904 if (type == QType::DS) {
a53e8fe3 5905 return 0;
3d5ebf10
RG
5906 }
5907 else if (type == QType::DNSKEY) {
5908 setLWResult(res, 0, true, false, true);
5909 addDNSKEY(keys, domain, 300, res->d_records);
5910 addRRSIG(keys, res->d_records, domain, 300);
5911 return 1;
5912 }
5913 else {
5914 if (isRootServer(ip)) {
5915 setLWResult(res, 0, false, false, true);
5916 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
5917 addDS(DNSName("com."), 300, res->d_records, keys);
5918 addRRSIG(keys, res->d_records, DNSName("."), 300);
5919 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5920 return 1;
5921 }
5922 else if (ip == ComboAddress("192.0.2.1:53")) {
a69867f2
RG
5923 if (domain == DNSName("com.")) {
5924 setLWResult(res, 0, true, false, true);
5925 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
5926 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5927 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
5928 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5929 }
5930 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
5931 setLWResult(res, 0, false, false, true);
5932 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
5933 addDS(DNSName(domain), 300, res->d_records, keys);
5934 addRRSIG(keys, res->d_records, DNSName("com."), 300);
5935 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
5936 }
3d5ebf10
RG
5937 return 1;
5938 }
5939 else if (ip == ComboAddress("192.0.2.2:53")) {
5940 setLWResult(res, 0, true, false, true);
a69867f2
RG
5941 if (type == QType::NS) {
5942 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
3d5ebf10 5943 addRRSIG(keys, res->d_records, domain, 300);
a69867f2 5944 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
3d5ebf10
RG
5945 addRRSIG(keys, res->d_records, domain, 300);
5946 }
a69867f2
RG
5947 else {
5948 if (domain == target) {
5949 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
5950 addRRSIG(keys, res->d_records, domain, 300);
5951 }
5952 else if (domain == targetCName) {
5953 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
5954 addRRSIG(keys, res->d_records, domain, 300);
5955 }
5956 }
3d5ebf10
RG
5957 return 1;
5958 }
5959 }
5960
5961 return 0;
5962 });
5963
5964 vector<DNSRecord> ret;
5965 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5966 BOOST_CHECK_EQUAL(res, RCode::NoError);
5967 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
5968 BOOST_REQUIRE_EQUAL(ret.size(), 4);
a69867f2 5969 BOOST_CHECK_EQUAL(queriesCount, 12);
3d5ebf10
RG
5970
5971 /* again, to test the cache */
5972 ret.clear();
5973 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
5974 BOOST_CHECK_EQUAL(res, RCode::NoError);
5975 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
5976 BOOST_REQUIRE_EQUAL(ret.size(), 4);
a69867f2 5977 BOOST_CHECK_EQUAL(queriesCount, 12);
3d5ebf10
RG
5978}
5979
5980BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname) {
5981 std::unique_ptr<SyncRes> sr;
a69867f2 5982 initSR(sr, true);
3d5ebf10
RG
5983
5984 g_dnssecmode = DNSSECMode::ValidateAll;
5985
5986 primeHints();
5987 const DNSName target("powerdns.com.");
5988 const DNSName targetCName("power-dns.com.");
5989 const ComboAddress targetCNameAddr("192.0.2.42");
5990 testkeysset_t keys;
5991
5992 auto luaconfsCopy = g_luaconfs.getCopy();
5993 luaconfsCopy.dsAnchors.clear();
5994 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
5995 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5996 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5997 generateKeyMaterial(DNSName("power-dns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
5998 g_luaconfs.setState(luaconfsCopy);
5999
6000 size_t queriesCount = 0;
6001
6002 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) {
6003 queriesCount++;
6004
6005 if (type == QType::DS) {
a53e8fe3 6006 if (domain == DNSName("power-dns.com.")) {
3d5ebf10
RG
6007 setLWResult(res, 0, false, false, true);
6008 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
6009 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), { QType::NS }, 600, res->d_records);
6010 addRRSIG(keys, res->d_records, DNSName("com."), 300);
6011 return 1;
6012 }
6013 }
6014 else if (type == QType::DNSKEY) {
6015 if (domain == g_rootdnsname || domain == DNSName("com.") || domain == DNSName("powerdns.com.")) {
6016 setLWResult(res, 0, true, false, true);
6017 addDNSKEY(keys, domain, 300, res->d_records);
6018 addRRSIG(keys, res->d_records, domain, 300);
6019 return 1;
6020 }
6021 else {
6022 setLWResult(res, 0, false, false, true);
6023 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
6024 return 1;
6025 }
6026 }
6027 else {
6028 if (isRootServer(ip)) {
6029 setLWResult(res, 0, false, false, true);
6030 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
6031 addDS(DNSName("com."), 300, res->d_records, keys);
6032 addRRSIG(keys, res->d_records, DNSName("."), 300);
6033 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
6034 return 1;
6035 }
6036 else if (ip == ComboAddress("192.0.2.1:53")) {
88cb0fe0
RG
6037 if (domain == DNSName("com.")) {
6038 setLWResult(res, 0, true, false, true);
a69867f2 6039 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
88cb0fe0
RG
6040 addRRSIG(keys, res->d_records, DNSName("com."), 300);
6041 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
6042 addRRSIG(keys, res->d_records, DNSName("com."), 300);
3d5ebf10 6043 }
88cb0fe0
RG
6044 else if (domain == DNSName("powerdns.com.") || domain == DNSName("power-dns.com.")) {
6045 setLWResult(res, 0, false, false, true);
6046 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
6047 if (domain == DNSName("powerdns.com.")) {
6048 addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
6049 }
6050 else if (domain == targetCName) {
6051 addNSECRecordToLW(domain, DNSName("z.power-dns.com."), { QType::NS }, 600, res->d_records);
6052 }
6053 addRRSIG(keys, res->d_records, DNSName("com."), 300);
6054 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
3d5ebf10 6055 }
3d5ebf10
RG
6056 return 1;
6057 }
6058 else if (ip == ComboAddress("192.0.2.2:53")) {
6059 setLWResult(res, 0, true, false, true);
88cb0fe0
RG
6060 if (type == QType::NS) {
6061 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
6062 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
3d5ebf10 6063 }
88cb0fe0
RG
6064 else {
6065 if (domain == DNSName("powerdns.com.")) {
6066 addRecordToLW(res, domain, QType::CNAME, targetCName.toString());
6067 /* No RRSIG -> Bogus */
6068 }
6069 else if (domain == targetCName) {
6070 addRecordToLW(res, domain, QType::A, targetCNameAddr.toString());
6071 }
3d5ebf10
RG
6072 }
6073 return 1;
6074 }
6075 }
6076
6077 return 0;
6078 });
6079
6080 vector<DNSRecord> ret;
6081 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6082 BOOST_CHECK_EQUAL(res, RCode::NoError);
6083 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
6084 /* no RRSIG to show */
6085 BOOST_CHECK_EQUAL(ret.size(), 2);
a69867f2 6086 BOOST_CHECK_EQUAL(queriesCount, 10);
3d5ebf10
RG
6087
6088 /* again, to test the cache */
6089 ret.clear();
6090 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6091 BOOST_CHECK_EQUAL(res, RCode::NoError);
6092 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
6093 BOOST_CHECK_EQUAL(ret.size(), 2);
a69867f2 6094 BOOST_CHECK_EQUAL(queriesCount, 10);
3d5ebf10
RG
6095}
6096
895449a5
RG
6097BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta) {
6098 std::unique_ptr<SyncRes> sr;
6099 initSR(sr, true);
6100
6101 g_dnssecmode = DNSSECMode::ValidateAll;
6102
6103 primeHints();
6104 const DNSName target("powerdns.com.");
6105 const ComboAddress targetAddr("192.0.2.42");
6106 testkeysset_t keys;
6107
6108 auto luaconfsCopy = g_luaconfs.getCopy();
6109 luaconfsCopy.dsAnchors.clear();
6110 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
6111 /* No key material for .com */
6112 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
6113 luaconfsCopy.dsAnchors[target].insert(keys[target].second);
6114 g_luaconfs.setState(luaconfsCopy);
6115
6116 size_t queriesCount = 0;
6117
6118 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) {
6119 queriesCount++;
6120
a53e8fe3 6121 if (type == QType::DNSKEY) {
895449a5
RG
6122 if (domain == g_rootdnsname || domain == DNSName("powerdns.com.")) {
6123 setLWResult(res, 0, true, false, true);
6124 addDNSKEY(keys, domain, 300, res->d_records);
6125 addRRSIG(keys, res->d_records, domain, 300);
6126 return 1;
6127 }
6128 else if (domain == DNSName("com.")) {
6129 setLWResult(res, 0, false, false, true);
6130 addRecordToLW(res, domain, QType::SOA, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
6131 return 1;
6132 }
6133 }
88cb0fe0 6134 else {
895449a5
RG
6135 if (isRootServer(ip)) {
6136 setLWResult(res, 0, false, false, true);
6137 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
6138 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS }, 600, res->d_records);
6139 addRRSIG(keys, res->d_records, DNSName("."), 300);
6140 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
6141 return 1;
6142 }
6143 else if (ip == ComboAddress("192.0.2.1:53")) {
88cb0fe0
RG
6144 if (target == domain) {
6145 setLWResult(res, 0, false, false, true);
6146 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
6147 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
6148 }
6149 else if (domain == DNSName("com.")) {
6150 setLWResult(res, 0, true, false, true);
6151 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
6152 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
6153 }
895449a5
RG
6154 return 1;
6155 }
6156 else if (ip == ComboAddress("192.0.2.2:53")) {
6157 setLWResult(res, 0, true, false, true);
88cb0fe0
RG
6158 if (type == QType::NS) {
6159 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
6160 }
6161 else {
6162 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
6163 }
895449a5
RG
6164 addRRSIG(keys, res->d_records, domain, 300);
6165 return 1;
6166 }
6167 }
6168
6169 return 0;
6170 });
6171
6172 vector<DNSRecord> ret;
6173 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6174 BOOST_CHECK_EQUAL(res, RCode::NoError);
6175 /* should be insecure but we have a TA for powerdns.com. */
6176 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
6177 /* We got a RRSIG */
6178 BOOST_REQUIRE_EQUAL(ret.size(), 2);
6179 BOOST_CHECK(ret[0].d_type == QType::A);
88cb0fe0
RG
6180 /* - NS com. (at . and com.)
6181 - NS powerdns.com (com. and powerdns.com.)
6182 - DNSKEY (. and powerdns.com.)
6183 - A powerdns.com
6184 */
6185 BOOST_CHECK_EQUAL(queriesCount, 7);
895449a5
RG
6186
6187 /* again, to test the cache */
6188 ret.clear();
6189 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6190 BOOST_CHECK_EQUAL(res, RCode::NoError);
6191 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
6192 BOOST_REQUIRE_EQUAL(ret.size(), 2);
6193 BOOST_CHECK(ret[0].d_type == QType::A);
88cb0fe0 6194 BOOST_CHECK_EQUAL(queriesCount, 7);
895449a5
RG
6195}
6196
6197BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig) {
6198 std::unique_ptr<SyncRes> sr;
6199 initSR(sr, true);
6200
6201 g_dnssecmode = DNSSECMode::ValidateAll;
6202
6203 primeHints();
6204 const DNSName target("powerdns.com.");
6205 const ComboAddress targetAddr("192.0.2.42");
6206 testkeysset_t keys;
6207
6208 auto luaconfsCopy = g_luaconfs.getCopy();
6209 luaconfsCopy.dsAnchors.clear();
6210 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
6211 /* No key material for .com */
6212 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
6213 luaconfsCopy.dsAnchors[target].insert(keys[target].second);
6214 g_luaconfs.setState(luaconfsCopy);
6215
6216 size_t queriesCount = 0;
6217
6218 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) {
6219 queriesCount++;
6220
a53e8fe3 6221 if (type == QType::DNSKEY) {
895449a5
RG
6222 if (domain == g_rootdnsname || domain == DNSName("powerdns.com.")) {
6223 setLWResult(res, 0, true, false, true);
6224 addDNSKEY(keys, domain, 300, res->d_records);
6225 addRRSIG(keys, res->d_records, domain, 300);
6226 return 1;
6227 }
6228 else if (domain == DNSName("com.")) {
6229 setLWResult(res, 0, false, false, true);
6230 addRecordToLW(res, domain, QType::SOA, ". yop. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
6231 return 1;
6232 }
6233 }
70b3fe7a
RG
6234 else {
6235 if (target.isPartOf(domain) && isRootServer(ip)) {
895449a5
RG
6236 setLWResult(res, 0, false, false, true);
6237 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
6238 addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS }, 600, res->d_records);
6239 addRRSIG(keys, res->d_records, DNSName("."), 300);
6240 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
6241 return 1;
6242 }
6243 else if (ip == ComboAddress("192.0.2.1:53")) {
70b3fe7a
RG
6244 if (target == domain) {
6245 setLWResult(res, 0, false, false, true);
6246 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
6247 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
6248 }
6249 else if (domain == DNSName("com.")) {
6250 setLWResult(res, 0, true, false, true);
6251 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
88cb0fe0 6252 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
70b3fe7a 6253 }
895449a5
RG
6254 return 1;
6255 }
70b3fe7a 6256 else if (domain == target && ip == ComboAddress("192.0.2.2:53")) {
895449a5 6257 setLWResult(res, 0, true, false, true);
70b3fe7a
RG
6258 if (type == QType::NS) {
6259 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
6260 }
6261 else {
6262 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
6263 }
895449a5
RG
6264 /* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
6265 return 1;
6266 }
6267 }
6268
6269 return 0;
6270 });
6271
6272 vector<DNSRecord> ret;
6273 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6274 BOOST_CHECK_EQUAL(res, RCode::NoError);
6275 /* should be insecure but we have a TA for powerdns.com., but no RRSIG so Bogus */
6276 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
6277 /* No RRSIG */
6278 BOOST_REQUIRE_EQUAL(ret.size(), 1);
6279 BOOST_CHECK(ret[0].d_type == QType::A);
88cb0fe0
RG
6280 /* - NS com. (at . and com.)
6281 - NS powerdns.com (com. and powerdns.com.)
6282 - DNSKEY (.)
6283 - A powerdns.com (no DNSKEY because no RRSIG)
6284 */
6285 BOOST_CHECK_EQUAL(queriesCount, 6);
895449a5
RG
6286
6287 /* again, to test the cache */
6288 ret.clear();
6289 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6290 BOOST_CHECK_EQUAL(res, RCode::NoError);
6291 BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
6292 BOOST_REQUIRE_EQUAL(ret.size(), 1);
6293 BOOST_CHECK(ret[0].d_type == QType::A);
88cb0fe0 6294 BOOST_CHECK_EQUAL(queriesCount, 6);
895449a5
RG
6295}
6296
6297#if 0
6298BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_hidden_cut) {
6299 std::unique_ptr<SyncRes> sr;
860d5e8e 6300 initSR(sr, true, true);
895449a5
RG
6301
6302 g_dnssecLOG = true;
6303 g_dnssecmode = DNSSECMode::ValidateAll;
6304
6305 primeHints();
6306 const DNSName target("gov.nl.ca.");
6307 const ComboAddress targetAddr("192.0.2.42");
6308 testkeysset_t keys;
6309
6310 auto luaconfsCopy = g_luaconfs.getCopy();
6311 luaconfsCopy.dsAnchors.clear();
6312 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
6313 generateKeyMaterial(DNSName("ca."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
6314
6315 g_luaconfs.setState(luaconfsCopy);
6316
6317 size_t queriesCount = 0;
6318
6319 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) {
6320 queriesCount++;
6321
6322 if (type == QType::DS) {
6323 if (domain == g_rootdnsname || domain == DNSName("ca.")) {
6324 setLWResult(res, 0, false, false, true);
a53e8fe3 6325 addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER);
895449a5
RG
6326 addRRSIG(keys, res->d_records, domain, 300);
6327 return 1;
6328 }
6329 else {
6330 setLWResult(res, 0, false, false, true);
6331 addRecordToLW(res, DNSName("ca."), QType::SOA, "jbq01.prd.cira.ca. admin-dns.cira.ca. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
6332 addNSECRecordToLW(DNSName("nl.ca."), DNSName("nm.ca."), { QType::NS }, 600, res->d_records);
6333 addRRSIG(keys, res->d_records, DNSName("ca."), 300);
6334 return 1;
6335 }
6336 }
6337 else if (type == QType::DNSKEY) {
6338 if (domain == g_rootdnsname || domain == DNSName("ca.")) {
6339 setLWResult(res, 0, true, false, true);
6340 addDNSKEY(keys, domain, 300, res->d_records);
6341 addRRSIG(keys, res->d_records, domain, 300);
6342 return 1;
6343 }
6344 else {
6345 setLWResult(res, 0, false, false, true);
6346 addRecordToLW(res, domain, QType::SOA, "jbq01.prd.cira.ca. admin-dns.cira.ca. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
6347 return 1;
6348 }
6349 }
6350 else if (domain == target) {
6351 if (isRootServer(ip)) {
6352 setLWResult(res, 0, false, false, true);
6353 addRecordToLW(res, "ca.", QType::NS, "c.ca-servers.ca.", DNSResourceRecord::AUTHORITY, 3600);
6354 addDS(DNSName("ca."), 300, res->d_records, keys);
6355 addRRSIG(keys, res->d_records, DNSName("."), 300);
6356 addRecordToLW(res, "c.ca-servers.ca.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
6357 return 1;
6358 }
6359 else if (ip == ComboAddress("192.0.2.1:53")) {
6360 setLWResult(res, 0, false, false, true);
6361 addRecordToLW(res, domain, QType::NS, "ns.gov.nl.ca.", DNSResourceRecord::AUTHORITY, 3600);
860d5e8e
RG
6362 /* denial of DS FOR nl.ca while sending a referral for gov.nl.ca !! */
6363 addNSECRecordToLW(DNSName("nl.ca"), DNSName("nm.ca."), { QType::NS }, 600, res->d_records);
895449a5
RG
6364 addRRSIG(keys, res->d_records, DNSName("ca."), 300);
6365 addRecordToLW(res, "ns.gov.nl.ca.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
6366 return 1;
6367 }
6368 else if (ip == ComboAddress("192.0.2.2:53")) {
6369 setLWResult(res, 0, true, false, true);
6370 addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
6371 return 1;
6372 }
6373 }
6374
6375 return 0;
6376 });
6377
6378 vector<DNSRecord> ret;
6379 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6380 BOOST_CHECK_EQUAL(res, RCode::NoError);
6381 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
6382 BOOST_REQUIRE_EQUAL(ret.size(), 1);
6383 BOOST_CHECK(ret[0].d_type == QType::A);
6384 /* only 5 because no DNSKEY query for powerdns.com (insecure) */
6385 BOOST_CHECK_EQUAL(queriesCount, 5);
6386
6387 /* again, to test the cache */
6388 ret.clear();
6389 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
6390 BOOST_CHECK_EQUAL(res, RCode::NoError);
6391 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
6392 BOOST_REQUIRE_EQUAL(ret.size(), 1);
6393 BOOST_CHECK(ret[0].d_type == QType::A);
6394 BOOST_CHECK_EQUAL(queriesCount, 5);
6395}
6396#endif /* 0 */
6397
6398BOOST_AUTO_TEST_CASE(test_dnssec_nta) {
6399 std::unique_ptr<SyncRes> sr;
6400 initSR(sr, true);
6401
6402 g_dnssecmode = DNSSECMode::ValidateAll;
6403
b7f378d1
RG
6404 primeHints();
6405 const DNSName target(".");
6406 testkeysset_t keys;
6407
6408 auto luaconfsCopy = g_luaconfs.getCopy();
6409 luaconfsCopy.dsAnchors.clear();
6410 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
6411 /* Add a NTA for "." */
6412 luaconfsCopy.negAnchors[g_rootdnsname] = "NTA for Root";
6413 g_luaconfs.setState(luaconfsCopy);
6414
6415 size_t queriesCount = 0;
6416
6417 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) {
6418 queriesCount++;
6419
6420 if (domain == target && type == QType::NS) {
6421
6422 setLWResult(res, 0, true, false, true);
6423 char addr[] = "a.root-servers.net.";
6424 for (char idx = 'a'; idx <= 'm'; idx++) {
6425 addr[0] = idx;
8455425c
RG
6426 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
6427 }
6428
6429 addRRSIG(keys, res->d_records, domain, 300);
6430
6431 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
6432 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
6433
6434 return 1;
6435 } else if (domain == target && type == QType::DNSKEY) {
6436
6437 setLWResult(res, 0, true, false, true);
6438
6439 /* No DNSKEY */
6440
6441 return 1;
6442 }
6443
6444 return 0;
6445 });
6446
6447 vector<DNSRecord> ret;
6448 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
6449 BOOST_CHECK_EQUAL(res, RCode::NoError);
6450 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
8455425c
RG
6451 /* 13 NS + 1 RRSIG */
6452 BOOST_REQUIRE_EQUAL(ret.size(), 14);
6453 BOOST_CHECK_EQUAL(queriesCount, 1);
b7f378d1
RG
6454
6455 /* again, to test the cache */
6456 ret.clear();
6457 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
6458 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 6459 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
b7f378d1
RG
6460 BOOST_REQUIRE_EQUAL(ret.size(), 14);
6461 BOOST_CHECK_EQUAL(queriesCount, 1);
8455425c
RG
6462}
6463
6464BOOST_AUTO_TEST_CASE(test_dnssec_no_ta) {
6465 std::unique_ptr<SyncRes> sr;
895449a5 6466 initSR(sr, true);
8455425c
RG
6467
6468 g_dnssecmode = DNSSECMode::ValidateAll;
6469
6470 primeHints();
6471 const DNSName target(".");
b7f378d1 6472 testkeysset_t keys;
8455425c
RG
6473
6474 /* Remove the root DS */
6475 auto luaconfsCopy = g_luaconfs.getCopy();
6476 luaconfsCopy.dsAnchors.clear();
6477 g_luaconfs.setState(luaconfsCopy);
6478
6479 size_t queriesCount = 0;
6480
6481 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) {
6482 queriesCount++;
6483
6484 if (domain == target && type == QType::NS) {
6485
6486 setLWResult(res, 0, true, false, true);
6487 char addr[] = "a.root-servers.net.";
6488 for (char idx = 'a'; idx <= 'm'; idx++) {
6489 addr[0] = idx;
6490 addRecordToLW(res, domain, QType::NS, std::string(addr), DNSResourceRecord::ANSWER, 3600);
6491 }
6492
6493 addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600);
6494 addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
6495
6496 return 1;
6497 }
6498
6499 return 0;
6500 });
6501
6502 vector<DNSRecord> ret;
6503 int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
b7f378d1
RG
6504 BOOST_CHECK_EQUAL(res, RCode::NoError);
6505 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
8455425c
RG
6506 /* 13 NS + 0 RRSIG */
6507 BOOST_REQUIRE_EQUAL(ret.size(), 13);
6508 BOOST_CHECK_EQUAL(queriesCount, 1);
b7f378d1
RG
6509
6510 /* again, to test the cache */
6511 ret.clear();
6512 res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
6513 BOOST_CHECK_EQUAL(res, RCode::NoError);
8455425c 6514 BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
b7f378d1
RG
6515 BOOST_REQUIRE_EQUAL(ret.size(), 13);
6516 BOOST_CHECK_EQUAL(queriesCount, 1);
8455425c
RG
6517}
6518
d6e797b8
RG
6519/*
6520// cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
6521
648bcbd1 6522- check out of band support
d6e797b8 6523
648bcbd1 6524- check preoutquery
d6e797b8 6525
30ee601a
RG
6526*/
6527
6528BOOST_AUTO_TEST_SUITE_END()