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