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