]>
Commit | Line | Data |
---|---|---|
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 | 15 | GlobalStateHolder<LuaConfigItems> g_luaconfs; |
2b20e918 | 16 | GlobalStateHolder<SuffixMatchNode> g_xdnssec; |
559b6c93 PL |
17 | GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames; |
18 | GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks; | |
b4ae1398 | 19 | GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames; |
2bbc9eb0 RP |
20 | std::unique_ptr<MemRecursorCache> g_recCache; |
21 | std::unique_ptr<NegCache> g_negCache; | |
c1c29961 | 22 | bool g_lowercaseOutgoing = false; |
e3257bdc OM |
23 | #if 0 |
24 | pdns::TaskQueue g_test_tasks; | |
25 | pdns::TaskQueue g_resolve_tasks; | |
26 | #endif | |
30ee601a RG |
27 | /* Fake some required functions we didn't want the trouble to |
28 | link with */ | |
42dcf516 | 29 | ArgvMap& arg() |
30ee601a RG |
30 | { |
31 | static ArgvMap theArg; | |
32 | return theArg; | |
33 | } | |
34 | ||
b6ae57b8 RG |
35 | BaseLua4::~BaseLua4() |
36 | { | |
37 | } | |
38 | ||
8b428a6b | 39 | void BaseLua4::getFeatures(Features& /* features */) |
b6ae57b8 RG |
40 | { |
41 | } | |
42 | ||
8b428a6b | 43 | bool 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 | 48 | bool 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 |
53 | RecursorLua4::~RecursorLua4() |
54 | { | |
55 | } | |
56 | ||
57 | void RecursorLua4::postPrepareContext() | |
58 | { | |
59 | } | |
60 | ||
61 | void RecursorLua4::postLoad() | |
62 | { | |
63 | } | |
64 | ||
8b428a6b | 65 | void RecursorLua4::getFeatures(Features& /* features */) |
b6ae57b8 RG |
66 | { |
67 | } | |
68 | ||
32b3e0ef | 69 | LWResult::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 | 82 | bool 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 | ||
122 | LuaConfigItems::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 | 132 | void 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 | 231 | void 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 | 256 | void setDNSSECValidation(std::unique_ptr<SyncRes>& sr, const DNSSECMode& mode) |
0c43f455 RG |
257 | { |
258 | sr->setDNSSECValidationRequested(true); | |
259 | g_dnssecmode = mode; | |
260 | } | |
261 | ||
86675669 | 262 | void 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 | 271 | void 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 | 276 | void 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 | 281 | bool 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 | 301 | void 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 | 323 | typedef std::unordered_map<DNSName, std::pair<DNSSECPrivateKey, DSRecordContent>> testkeysset_t; |
b7f378d1 | 324 | |
86675669 | 325 | bool 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 | 383 | void 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 | 400 | bool 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 | 418 | void 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 | 436 | 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, 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 | 458 | 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, 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 */ |
467 | void 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 | 477 | void 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 | 488 | void 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 | 498 | void 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 | 504 | LWResult::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 | 554 | LWResult::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 | } |