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