]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursordist/test-syncres_cc.cc
rec: CVE-2023-50387 and CVE-2023-50868
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc.cc
CommitLineData
1c2d079d 1#ifndef BOOST_TEST_DYN_LINK
30ee601a 2#define BOOST_TEST_DYN_LINK
1c2d079d
FM
3#endif
4
30ee601a
RG
5#include <boost/test/unit_test.hpp>
6
a401a9be 7#include "aggressive_nsec.hh"
95823c07 8#include "base32.hh"
30ee601a 9#include "lua-recursor4.hh"
30ee601a 10#include "root-dnssec.hh"
87c4554a 11#include "rec-taskqueue.hh"
86675669 12#include "test-syncres_cc.hh"
1e325a92 13#include "recpacketcache.hh"
30ee601a 14
30ee601a 15GlobalStateHolder<LuaConfigItems> g_luaconfs;
2b20e918 16GlobalStateHolder<SuffixMatchNode> g_xdnssec;
559b6c93
PL
17GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames;
18GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks;
b4ae1398 19GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames;
2bbc9eb0
RP
20std::unique_ptr<MemRecursorCache> g_recCache;
21std::unique_ptr<NegCache> g_negCache;
c1c29961 22bool g_lowercaseOutgoing = false;
e3257bdc
OM
23#if 0
24pdns::TaskQueue g_test_tasks;
25pdns::TaskQueue g_resolve_tasks;
26#endif
30ee601a
RG
27/* Fake some required functions we didn't want the trouble to
28 link with */
42dcf516 29ArgvMap& arg()
30ee601a
RG
30{
31 static ArgvMap theArg;
32 return theArg;
33}
34
b6ae57b8
RG
35BaseLua4::~BaseLua4()
36{
37}
38
8b428a6b 39void BaseLua4::getFeatures(Features& /* features */)
b6ae57b8
RG
40{
41}
42
8b428a6b 43bool RecursorLua4::preoutquery(const ComboAddress& /* ns */, const ComboAddress& /* requestor */, const DNSName& /* query */, const QType& /* qtype */, bool /* isTcp */, vector<DNSRecord>& /* res */, int& /* ret */, RecEventTrace& /* et */, const struct timeval& /* tv */) const
30ee601a
RG
44{
45 return false;
46}
47
8b428a6b 48bool RecursorLua4::policyHitEventFilter(const ComboAddress& /* remote */, const DNSName& /* qname */, const QType& /* qtype */, bool /* tcp */, DNSFilterEngine::Policy& /* policy */, std::unordered_set<std::string>& /* tags */, std::unordered_map<std::string, bool>& /* discardedPolicies */) const
acf86ed7
RG
49{
50 return false;
51}
52
b6ae57b8
RG
53RecursorLua4::~RecursorLua4()
54{
55}
56
57void RecursorLua4::postPrepareContext()
58{
59}
60
61void RecursorLua4::postLoad()
62{
63}
64
8b428a6b 65void RecursorLua4::getFeatures(Features& /* features */)
b6ae57b8
RG
66{
67}
68
32b3e0ef 69LWResult::Result asyncresolve(const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, const ResolveContext& /* context */, const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& /* outgoingLoggers */, const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& /* fstrmLoggers */, const std::set<uint16_t>& /* exportTypes */, LWResult* /* res */, bool* /* chained */)
30ee601a 70{
308f4c43 71 return LWResult::Result::Timeout;
30ee601a
RG
72}
73
74/* primeHints() is only here for now because it
75 was way too much trouble to link with the real one.
76 We should fix this, empty functions are one thing, but this is
77 bad.
78*/
79
80#include "root-addresses.hh"
81
1d52e318 82bool primeHints(time_t now)
30ee601a
RG
83{
84 vector<DNSRecord> nsset;
ccfadb6c 85 if (!g_recCache)
2bbc9eb0 86 g_recCache = std::make_unique<MemRecursorCache>();
ccfadb6c 87 if (!g_negCache)
2bbc9eb0 88 g_negCache = std::make_unique<NegCache>();
30ee601a
RG
89
90 DNSRecord arr, aaaarr, nsrr;
42dcf516
OM
91 nsrr.d_name = g_rootdnsname;
92 arr.d_type = QType::A;
93 aaaarr.d_type = QType::AAAA;
94 nsrr.d_type = QType::NS;
1d52e318 95 arr.d_ttl = aaaarr.d_ttl = nsrr.d_ttl = now + 3600000;
30ee601a 96
42dcf516 97 for (char c = 'a'; c <= 'm'; ++c) {
e4f772ce 98 char templ[40];
42dcf516
OM
99 strncpy(templ, "a.root-servers.net.", sizeof(templ) - 1);
100 templ[sizeof(templ) - 1] = '\0';
101 *templ = c;
102 aaaarr.d_name = arr.d_name = DNSName(templ);
d06dcda4
RG
103 nsrr.setContent(std::make_shared<NSRecordContent>(DNSName(templ)));
104 arr.setContent(std::make_shared<ARecordContent>(ComboAddress(rootIps4[c - 'a'])));
30ee601a
RG
105 vector<DNSRecord> aset;
106 aset.push_back(arr);
d06dcda4 107 g_recCache->replace(now, DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
5c7e7d48 108 if (!rootIps6[c - 'a'].empty()) {
d06dcda4 109 aaaarr.setContent(std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c - 'a'])));
30ee601a
RG
110
111 vector<DNSRecord> aaaaset;
112 aaaaset.push_back(aaaarr);
d06dcda4 113 g_recCache->replace(now, DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
30ee601a
RG
114 }
115
116 nsset.push_back(nsrr);
117 }
d06dcda4 118 g_recCache->replace(now, g_rootdnsname, QType(QType::NS), nsset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname); // and stuff in the cache
b3dd32d2 119 return true;
30ee601a
RG
120}
121
122LuaConfigItems::LuaConfigItems()
123{
42dcf516
OM
124 for (const auto& dsRecord : rootDSs) {
125 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
30ee601a
RG
126 dsAnchors[g_rootdnsname].insert(*ds);
127 }
128}
129
130/* Some helpers functions */
131
86675669 132void initSR(bool debug)
30ee601a 133{
e6a9dde5
PL
134 g_log.setName("test");
135 g_log.disableSyslog(true);
b4c8789a 136
30ee601a 137 if (debug) {
e6a9dde5
PL
138 g_log.setLoglevel((Logger::Urgency)(6)); // info and up
139 g_log.toConsole(Logger::Info);
30ee601a 140 }
b4c8789a 141 else {
e6a9dde5
PL
142 g_log.setLoglevel(Logger::None);
143 g_log.toConsole(Logger::Error);
b4c8789a 144 }
30ee601a 145
1e325a92 146 RecursorPacketCache::s_refresh_ttlperc = 0;
e6bc8d54
OM
147 MemRecursorCache::s_maxServedStaleExtensions = 0;
148 NegCache::s_maxServedStaleExtensions = 0;
2bbc9eb0
RP
149 g_recCache = std::make_unique<MemRecursorCache>();
150 g_negCache = std::make_unique<NegCache>();
30ee601a 151
30ee601a 152 SyncRes::s_maxqperq = 50;
86f95f85 153 SyncRes::s_maxnsaddressqperq = 10;
42dcf516 154 SyncRes::s_maxtotusec = 1000 * 7000;
30ee601a
RG
155 SyncRes::s_maxdepth = 40;
156 SyncRes::s_maxnegttl = 3600;
b9473937 157 SyncRes::s_maxbogusttl = 3600;
30ee601a
RG
158 SyncRes::s_maxcachettl = 86400;
159 SyncRes::s_packetcachettl = 3600;
160 SyncRes::s_packetcacheservfailttl = 60;
161 SyncRes::s_serverdownmaxfails = 64;
162 SyncRes::s_serverdownthrottletime = 60;
7b1d1a7d 163 SyncRes::s_doIPv4 = true;
30ee601a 164 SyncRes::s_doIPv6 = true;
e9f9b8ec
RG
165 SyncRes::s_ecsipv4limit = 24;
166 SyncRes::s_ecsipv6limit = 56;
bdceeb7e
RG
167 SyncRes::s_ecsipv4cachelimit = 24;
168 SyncRes::s_ecsipv6cachelimit = 56;
2cbe6a45 169 SyncRes::s_ecscachelimitttl = 0;
f58c8379 170 SyncRes::s_rootNXTrust = true;
d40a915b 171 SyncRes::s_hardenNXD = SyncRes::HardenNXD::DNSSEC;
d6e797b8 172 SyncRes::s_minimumTTL = 0;
5cf4b2e7 173 SyncRes::s_minimumECSTTL = 0;
648bcbd1 174 SyncRes::s_serverID = "PowerDNS Unit Tests Server ID";
2fe3354d
CH
175 SyncRes::clearEDNSLocalSubnets();
176 SyncRes::addEDNSLocalSubnet("0.0.0.0/0");
177 SyncRes::addEDNSLocalSubnet("::/0");
178 SyncRes::clearEDNSRemoteSubnets();
9065eb05 179 SyncRes::clearEDNSDomains();
9065eb05 180 SyncRes::clearDontQuery();
2fe3354d 181 SyncRes::setECSScopeZeroAddress(Netmask("127.0.0.1/32"));
357d1186 182 SyncRes::s_qnameminimization = false;
b5715cff
O
183 SyncRes::s_nonresolvingnsmaxfails = 0;
184 SyncRes::s_nonresolvingnsthrottletime = 0;
5dda7680 185 SyncRes::s_refresh_ttlperc = 0;
20c299f8 186 SyncRes::s_save_parent_ns_set = true;
55badaf8
OM
187 SyncRes::s_maxnsperresolve = 13;
188 SyncRes::s_locked_ttlperc = 0;
3f15edc8 189 SyncRes::s_minimize_one_label = 4;
831baae7 190 SyncRes::s_max_minimize_count = 10;
648bcbd1 191
a712cb56 192 SyncRes::clearNSSpeeds();
690b86b7 193 BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0U);
a712cb56 194 SyncRes::clearEDNSStatuses();
690b86b7 195 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0U);
a712cb56 196 SyncRes::clearThrottle();
690b86b7 197 BOOST_CHECK_EQUAL(SyncRes::getThrottledServersSize(), 0U);
a712cb56 198 SyncRes::clearFailedServers();
690b86b7 199 BOOST_CHECK_EQUAL(SyncRes::getFailedServersSize(), 0U);
b5715cff
O
200 SyncRes::clearNonResolvingNS();
201 BOOST_CHECK_EQUAL(SyncRes::getNonResolvingNSSize(), 0U);
4e45e5bc
O
202 SyncRes::clearSaveParentsNSSets();
203 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 0U);
a712cb56 204
c9783016
RG
205 SyncRes::clearECSStats();
206
648bcbd1
RG
207 auto luaconfsCopy = g_luaconfs.getCopy();
208 luaconfsCopy.dfe.clear();
8455425c 209 luaconfsCopy.dsAnchors.clear();
42dcf516
OM
210 for (const auto& dsRecord : rootDSs) {
211 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
8455425c
RG
212 luaconfsCopy.dsAnchors[g_rootdnsname].insert(*ds);
213 }
214 luaconfsCopy.negAnchors.clear();
648bcbd1
RG
215 g_luaconfs.setState(luaconfsCopy);
216
8455425c 217 g_dnssecmode = DNSSECMode::Off;
b7c40613 218 g_maxNSEC3Iterations = 2500;
8455425c 219
a401a9be 220 g_aggressiveNSECCache.reset();
dcf64a6e
OM
221 AggressiveNSECCache::s_maxNSEC3CommonPrefix = AggressiveNSECCache::s_default_maxNSEC3CommonPrefix;
222
e3257bdc 223 taskQueueClear();
a401a9be 224
42dcf516
OM
225 ::arg().set("version-string", "string reported on version.pdns or version.bind") = "PowerDNS Unit Tests";
226 ::arg().set("rng") = "auto";
227 ::arg().set("entropy-source") = "/dev/urandom";
d56903d0 228 ::arg().set("hint-file") = "";
30ee601a
RG
229}
230
86675669 231void initSR(std::unique_ptr<SyncRes>& sr, bool dnssec, bool debug, time_t fakeNow)
30ee601a
RG
232{
233 struct timeval now;
d6e797b8
RG
234 if (fakeNow > 0) {
235 now.tv_sec = fakeNow;
236 now.tv_usec = 0;
237 }
238 else {
239 Utility::gettimeofday(&now, 0);
240 }
241
86675669 242 initSR(debug);
895449a5 243
2bbc9eb0 244 sr = std::make_unique<SyncRes>(now);
895449a5 245 sr->setDoEDNS0(true);
0c43f455
RG
246 if (dnssec) {
247 sr->setDoDNSSEC(dnssec);
248 }
249
895449a5
RG
250 sr->setLogMode(debug == false ? SyncRes::LogNone : SyncRes::Log);
251
a712cb56 252 SyncRes::setDomainMap(std::make_shared<SyncRes::domainmap_t>());
ccfadb6c 253 g_negCache->clear();
30ee601a
RG
254}
255
86675669 256void setDNSSECValidation(std::unique_ptr<SyncRes>& sr, const DNSSECMode& mode)
0c43f455
RG
257{
258 sr->setDNSSECValidationRequested(true);
259 g_dnssecmode = mode;
260}
261
86675669 262void setLWResult(LWResult* res, int rcode, bool aa, bool tc, bool edns, bool validpacket)
30ee601a
RG
263{
264 res->d_rcode = rcode;
265 res->d_aabit = aa;
266 res->d_tcbit = tc;
267 res->d_haveEDNS = edns;
269ac73d 268 res->d_validpacket = validpacket;
30ee601a
RG
269}
270
86675669 271void addRecordToLW(LWResult* res, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl)
d6e797b8
RG
272{
273 addRecordToList(res->d_records, name, type, content, place, ttl);
30ee601a
RG
274}
275
86675669 276void addRecordToLW(LWResult* res, const std::string& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl)
30ee601a
RG
277{
278 addRecordToLW(res, DNSName(name), type, content, place, ttl);
279}
280
86675669 281bool isRootServer(const ComboAddress& ip)
30ee601a 282{
8455425c 283 if (ip.isIPv4()) {
5c7e7d48 284 for (size_t idx = 0; idx < rootIps4.size(); idx++) {
8455425c
RG
285 if (ip.toString() == rootIps4[idx]) {
286 return true;
287 }
30ee601a
RG
288 }
289 }
8455425c 290 else {
5c7e7d48 291 for (size_t idx = 0; idx < rootIps6.size(); idx++) {
8455425c
RG
292 if (ip.toString() == rootIps6[idx]) {
293 return true;
294 }
30ee601a
RG
295 }
296 }
8455425c 297
30ee601a
RG
298 return false;
299}
300
c1e7b833 301void computeRRSIG(const DNSSECPrivateKey& dpk, const DNSName& signer, const DNSName& signQName, uint16_t signQType, uint32_t signTTL, uint32_t sigValidity, RRSIGRecordContent& rrc, const sortedRecords_t& toSign, boost::optional<uint8_t> algo, boost::optional<uint32_t> inception, boost::optional<time_t> now)
8455425c 302{
1e2e06f1
RG
303 if (!now) {
304 now = time(nullptr);
305 }
8455425c 306 DNSKEYRecordContent drc = dpk.getDNSKEY();
a2c6e554 307 const auto& rc = dpk.getKey();
8455425c
RG
308
309 rrc.d_type = signQType;
5a5c53b8 310 rrc.d_labels = signQName.countLabels() - (signQName.isWildcard() ? 1 : 0);
8455425c 311 rrc.d_originalttl = signTTL;
1e2e06f1
RG
312 rrc.d_siginception = inception ? *inception : (*now - 10);
313 rrc.d_sigexpire = *now + sigValidity;
8455425c 314 rrc.d_signer = signer;
8455425c 315 rrc.d_tag = drc.getTag();
3d5ebf10 316 rrc.d_algorithm = algo ? *algo : drc.d_algorithm;
8455425c
RG
317
318 std::string msg = getMessageForRRSET(signQName, rrc, toSign);
319
320 rrc.d_signature = rc->sign(msg);
321}
322
42dcf516 323typedef std::unordered_map<DNSName, std::pair<DNSSECPrivateKey, DSRecordContent>> testkeysset_t;
b7f378d1 324
86675669 325bool addRRSIG(const testkeysset_t& keys, std::vector<DNSRecord>& records, const DNSName& signer, uint32_t sigValidity, bool broken, boost::optional<uint8_t> algo, boost::optional<DNSName> wildcard, boost::optional<time_t> now)
8455425c
RG
326{
327 if (records.empty()) {
5374b03b 328 return false;
8455425c
RG
329 }
330
331 const auto it = keys.find(signer);
332 if (it == keys.cend()) {
86f1af1c 333 throw std::runtime_error("No DNSKEY found for " + signer.toLogString() + ", unable to compute the requested RRSIG");
8455425c
RG
334 }
335
15e973d6
OM
336 DNSName name;
337 uint16_t type{QType::ENT};
338 DNSResourceRecord::Place place{DNSResourceRecord::ANSWER};
339 uint32_t ttl{0};
340 bool found = false;
341
342 /* locate the last non-RRSIG record */
343 for (auto recordIterator = records.rbegin(); recordIterator != records.rend(); ++recordIterator) {
344 if (recordIterator->d_type != QType::RRSIG) {
345 name = recordIterator->d_name;
346 type = recordIterator->d_type;
347 place = recordIterator->d_place;
348 ttl = recordIterator->d_ttl;
349 found = true;
350 break;
351 }
352 }
353
354 if (!found) {
355 throw std::runtime_error("Unable to locate the record that the RRSIG should cover");
356 }
8455425c 357
c1e7b833 358 sortedRecords_t recordcontents;
f0c604d5 359 for (const auto& record : records) {
8455425c 360 if (record.d_name == name && record.d_type == type) {
d06dcda4 361 recordcontents.insert(record.getContent());
8455425c
RG
362 }
363 }
364
365 RRSIGRecordContent rrc;
15e973d6 366 computeRRSIG(it->second.first, signer, wildcard ? *wildcard : name, type, ttl, sigValidity, rrc, recordcontents, algo, boost::none, now);
3d5ebf10
RG
367 if (broken) {
368 rrc.d_signature[0] ^= 42;
369 }
8455425c
RG
370
371 DNSRecord rec;
dbbef467 372 rec.d_type = QType::RRSIG;
15e973d6
OM
373 rec.d_place = place;
374 rec.d_name = name;
375 rec.d_ttl = ttl;
8455425c 376
d06dcda4 377 rec.setContent(std::make_shared<RRSIGRecordContent>(rrc));
8455425c 378 records.push_back(rec);
5374b03b
RG
379
380 return true;
8455425c
RG
381}
382
86675669 383void addDNSKEY(const testkeysset_t& keys, const DNSName& signer, uint32_t ttl, std::vector<DNSRecord>& records)
8455425c
RG
384{
385 const auto it = keys.find(signer);
386 if (it == keys.cend()) {
86f1af1c 387 throw std::runtime_error("No DNSKEY found for " + signer.toLogString());
8455425c
RG
388 }
389
390 DNSRecord rec;
391 rec.d_place = DNSResourceRecord::ANSWER;
392 rec.d_name = signer;
393 rec.d_type = QType::DNSKEY;
394 rec.d_ttl = ttl;
395
d06dcda4 396 rec.setContent(std::make_shared<DNSKEYRecordContent>(it->second.first.getDNSKEY()));
8455425c
RG
397 records.push_back(rec);
398}
399
86675669 400bool addDS(const DNSName& domain, uint32_t ttl, std::vector<DNSRecord>& records, const testkeysset_t& keys, DNSResourceRecord::Place place)
8455425c 401{
b7f378d1
RG
402 const auto it = keys.find(domain);
403 if (it == keys.cend()) {
5374b03b 404 return false;
8455425c
RG
405 }
406
b7f378d1
RG
407 DNSRecord rec;
408 rec.d_name = domain;
409 rec.d_type = QType::DS;
a53e8fe3 410 rec.d_place = place;
b7f378d1 411 rec.d_ttl = ttl;
d06dcda4 412 rec.setContent(std::make_shared<DSRecordContent>(it->second.second));
8455425c 413
b7f378d1 414 records.push_back(rec);
5374b03b 415 return true;
8455425c
RG
416}
417
42dcf516 418void addNSECRecordToLW(const DNSName& domain, const DNSName& next, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records)
8455425c
RG
419{
420 NSECRecordContent nrc;
421 nrc.d_next = next;
27d4a65b
RG
422 for (const auto& type : types) {
423 nrc.set(type);
424 }
8455425c
RG
425
426 DNSRecord rec;
427 rec.d_name = domain;
428 rec.d_ttl = ttl;
429 rec.d_type = QType::NSEC;
d06dcda4 430 rec.setContent(std::make_shared<NSECRecordContent>(std::move(nrc)));
8455425c
RG
431 rec.d_place = DNSResourceRecord::AUTHORITY;
432
433 records.push_back(rec);
434}
435
c1797419 436void 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, bool optOut)
95823c07
RG
437{
438 NSEC3RecordContent nrc;
439 nrc.d_algorithm = 1;
c1797419 440 nrc.d_flags = optOut ? 1 : 0;
95823c07
RG
441 nrc.d_iterations = iterations;
442 nrc.d_salt = salt;
443 nrc.d_nexthash = hashedNext;
27d4a65b
RG
444 for (const auto& type : types) {
445 nrc.set(type);
446 }
95823c07
RG
447
448 DNSRecord rec;
449 rec.d_name = hashedName;
450 rec.d_ttl = ttl;
451 rec.d_type = QType::NSEC3;
d06dcda4 452 rec.setContent(std::make_shared<NSEC3RecordContent>(std::move(nrc)));
95823c07
RG
453 rec.d_place = DNSResourceRecord::AUTHORITY;
454
455 records.push_back(rec);
456}
457
c1797419 458void addNSEC3UnhashedRecordToLW(const DNSName& domain, const DNSName& zone, const std::string& next, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records, unsigned int iterations, bool optOut)
95823c07
RG
459{
460 static const std::string salt = "deadbeef";
95823c07
RG
461 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
462
c1797419 463 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, next, salt, iterations, types, ttl, records, optOut);
95823c07
RG
464}
465
eca47c4d
RG
466/* Proves a NODATA (name exists, type does not) but the next owner name is right behind, so it should not prove anything else unless we are very unlucky */
467void addNSEC3NoDataNarrowRecordToLW(const DNSName& domain, const DNSName& zone, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records, unsigned int iterations, bool optOut)
468{
469 static const std::string salt = "deadbeef";
470 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
471 std::string hashedNext(hashed);
472 incrementHash(hashedNext);
473
474 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, hashedNext, salt, iterations, types, ttl, records, optOut);
475}
476
c1797419 477void addNSEC3NarrowRecordToLW(const DNSName& domain, const DNSName& zone, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records, unsigned int iterations, bool optOut)
95823c07
RG
478{
479 static const std::string salt = "deadbeef";
95823c07 480 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
95823c07
RG
481 std::string hashedNext(hashed);
482 incrementHash(hashedNext);
483 decrementHash(hashed);
484
c1797419 485 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, hashedNext, salt, iterations, types, ttl, records, optOut);
95823c07
RG
486}
487
86675669 488void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys)
8455425c
RG
489{
490 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(algo));
b7f378d1 491 dcke->create((algo <= 10) ? 2048 : dcke->getBits());
8455425c 492 DNSSECPrivateKey dpk;
a456662f 493 dpk.setKey(dcke, 256);
8455425c 494 DSRecordContent ds = makeDSFromDNSKey(name, dpk.getDNSKEY(), digest);
42dcf516 495 keys[name] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, ds);
b7f378d1
RG
496}
497
42dcf516 498void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys, map<DNSName, dsmap_t>& dsAnchors)
b7f378d1
RG
499{
500 generateKeyMaterial(name, algo, digest, keys);
501 dsAnchors[name].insert(keys[name].second);
8455425c
RG
502}
503
308f4c43 504LWResult::Result genericDSAndDNSKEYHandler(LWResult* res, const DNSName& domain, DNSName auth, int type, const testkeysset_t& keys, bool proveCut, boost::optional<time_t> now, bool nsec3, bool optOut)
5374b03b
RG
505{
506 if (type == QType::DS) {
507 auth.chopOff();
508
509 setLWResult(res, 0, true, false, true);
510
511 if (addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER)) {
7ced0738 512 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
5374b03b
RG
513 }
514 else {
515 addRecordToLW(res, auth, QType::SOA, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
516
517 /* if the auth zone is signed, we need to provide a secure denial */
518 const auto it = keys.find(auth);
519 if (it != keys.cend()) {
520 /* sign the SOA */
7ced0738 521 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
5374b03b 522 /* add a NSEC denying the DS */
b2621209 523 std::set<uint16_t> types = {QType::RRSIG};
f4de85a3
RG
524 if (proveCut) {
525 types.insert(QType::NS);
526 }
527
c1797419 528 if (!nsec3) {
a401a9be 529 addNSECRecordToLW(domain, DNSName("+") + domain, types, 600, res->d_records);
c1797419
RG
530 }
531 else {
95f79e18
RG
532 DNSName next(DNSName("z") + domain);
533 next.makeUsRelative(auth);
534 addNSEC3UnhashedRecordToLW(domain, auth, next.toString(), types, 600, res->d_records, 10, optOut);
c1797419
RG
535 }
536
7ced0738 537 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
5374b03b
RG
538 }
539 }
540
308f4c43 541 return LWResult::Result::Success;
5374b03b
RG
542 }
543
544 if (type == QType::DNSKEY) {
545 setLWResult(res, 0, true, false, true);
dbbef467 546 addDNSKEY(keys, domain, 300, res->d_records);
1d52e318 547 addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, now);
308f4c43 548 return LWResult::Result::Success;
5374b03b
RG
549 }
550
308f4c43 551 return LWResult::Result::Timeout;
5374b03b
RG
552}
553
308f4c43 554LWResult::Result basicRecordsForQnameMinimization(LWResult* res, const DNSName& domain, int type)
42dcf516 555{
86675669
OM
556 if (domain == DNSName(".") && type == QType::A) {
557 setLWResult(res, 0, true);
558 addRecordToLW(res, DNSName("."), QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2019042400 1800 900 604800 86400", DNSResourceRecord::AUTHORITY);
308f4c43 559 return LWResult::Result::Success;
648bcbd1 560 }
86675669
OM
561 if (domain == DNSName("com") && type == QType::A) {
562 setLWResult(res, 0, true);
563 addRecordToLW(res, DNSName("com"), QType::NS, "ns1.com", DNSResourceRecord::AUTHORITY);
564 addRecordToLW(res, DNSName("ns1.com"), QType::A, "1.2.3.4", DNSResourceRecord::ADDITIONAL);
308f4c43 565 return LWResult::Result::Success;
c9783016 566 }
86675669
OM
567 if (domain == DNSName("ns1.com") && type == QType::A) {
568 setLWResult(res, 0, true);
569 addRecordToLW(res, DNSName("ns1.com"), QType::A, "1.2.3.4");
308f4c43 570 return LWResult::Result::Success;
c9783016 571 }
86675669
OM
572 if (domain == DNSName("powerdns.com") && type == QType::A) {
573 setLWResult(res, 0, true);
574 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com", DNSResourceRecord::AUTHORITY);
575 addRecordToLW(res, DNSName("ns1.powerdns.com"), QType::A, "4.5.6.7", DNSResourceRecord::ADDITIONAL);
308f4c43 576 return LWResult::Result::Success;
c9783016 577 }
86675669
OM
578 if (domain == DNSName("powerdns.com") && type == QType::NS) {
579 setLWResult(res, 0, true);
580 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com");
581 addRecordToLW(res, DNSName("ns1.powerdns.com"), QType::A, "4.5.6.7", DNSResourceRecord::ADDITIONAL);
308f4c43 582 return LWResult::Result::Success;
c9783016 583 }
308f4c43 584 return LWResult::Result::Timeout;
778bcea6 585}