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