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