]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/syncres.cc
383de1e2c59eb61edea6dc56eee48f8024693240
[thirdparty/pdns.git] / pdns / syncres.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "arguments.hh"
27 #include "aggressive_nsec.hh"
28 #include "cachecleaner.hh"
29 #include "dns_random.hh"
30 #include "dnsparser.hh"
31 #include "dnsrecords.hh"
32 #include "ednssubnet.hh"
33 #include "logger.hh"
34 #include "lua-recursor4.hh"
35 #include "rec-lua-conf.hh"
36 #include "syncres.hh"
37 #include "dnsseckeeper.hh"
38 #include "validate-recursor.hh"
39 #include "rec-taskqueue.hh"
40
41 thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage;
42 thread_local std::unique_ptr<addrringbuf_t> t_timeouts;
43
44 std::unique_ptr<NetmaskGroup> SyncRes::s_dontQuery{nullptr};
45 NetmaskGroup SyncRes::s_ednslocalsubnets;
46 NetmaskGroup SyncRes::s_ednsremotesubnets;
47 SuffixMatchNode SyncRes::s_ednsdomains;
48 EDNSSubnetOpts SyncRes::s_ecsScopeZero;
49 string SyncRes::s_serverID;
50 SyncRes::LogMode SyncRes::s_lm;
51 const std::unordered_set<QType> SyncRes::s_redirectionQTypes = {QType::CNAME, QType::DNAME};
52 LockGuarded<fails_t<ComboAddress>> SyncRes::s_fails;
53 LockGuarded<fails_t<DNSName>> SyncRes::s_nonresolving;
54
55 unsigned int SyncRes::s_maxnegttl;
56 unsigned int SyncRes::s_maxbogusttl;
57 unsigned int SyncRes::s_maxcachettl;
58 unsigned int SyncRes::s_maxqperq;
59 unsigned int SyncRes::s_maxnsaddressqperq;
60 unsigned int SyncRes::s_maxtotusec;
61 unsigned int SyncRes::s_maxdepth;
62 unsigned int SyncRes::s_minimumTTL;
63 unsigned int SyncRes::s_minimumECSTTL;
64 unsigned int SyncRes::s_packetcachettl;
65 unsigned int SyncRes::s_packetcacheservfailttl;
66 unsigned int SyncRes::s_serverdownmaxfails;
67 unsigned int SyncRes::s_serverdownthrottletime;
68 unsigned int SyncRes::s_nonresolvingnsmaxfails;
69 unsigned int SyncRes::s_nonresolvingnsthrottletime;
70 unsigned int SyncRes::s_ecscachelimitttl;
71 pdns::stat_t SyncRes::s_authzonequeries;
72 pdns::stat_t SyncRes::s_queries;
73 pdns::stat_t SyncRes::s_outgoingtimeouts;
74 pdns::stat_t SyncRes::s_outgoing4timeouts;
75 pdns::stat_t SyncRes::s_outgoing6timeouts;
76 pdns::stat_t SyncRes::s_outqueries;
77 pdns::stat_t SyncRes::s_tcpoutqueries;
78 pdns::stat_t SyncRes::s_dotoutqueries;
79 pdns::stat_t SyncRes::s_throttledqueries;
80 pdns::stat_t SyncRes::s_dontqueries;
81 pdns::stat_t SyncRes::s_qnameminfallbacksuccess;
82 pdns::stat_t SyncRes::s_unreachables;
83 pdns::stat_t SyncRes::s_ecsqueries;
84 pdns::stat_t SyncRes::s_ecsresponses;
85 std::map<uint8_t, pdns::stat_t> SyncRes::s_ecsResponsesBySubnetSize4;
86 std::map<uint8_t, pdns::stat_t> SyncRes::s_ecsResponsesBySubnetSize6;
87
88 uint8_t SyncRes::s_ecsipv4limit;
89 uint8_t SyncRes::s_ecsipv6limit;
90 uint8_t SyncRes::s_ecsipv4cachelimit;
91 uint8_t SyncRes::s_ecsipv6cachelimit;
92 bool SyncRes::s_ecsipv4nevercache;
93 bool SyncRes::s_ecsipv6nevercache;
94
95 bool SyncRes::s_doIPv4;
96 bool SyncRes::s_doIPv6;
97 bool SyncRes::s_nopacketcache;
98 bool SyncRes::s_rootNXTrust;
99 bool SyncRes::s_noEDNS;
100 bool SyncRes::s_qnameminimization;
101 SyncRes::HardenNXD SyncRes::s_hardenNXD;
102 unsigned int SyncRes::s_refresh_ttlperc;
103 int SyncRes::s_tcp_fast_open;
104 bool SyncRes::s_tcp_fast_open_connect;
105 bool SyncRes::s_dot_to_port_853;
106 int SyncRes::s_event_trace_enabled;
107
108 #define LOG(x) if(d_lm == Log) { g_log <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
109
110 // A helper function to print a double with specific printf format.
111 // Not using boost::format since it is not thread safe while calling
112 // into locale handling code according to tsan.
113 // This allocates a string, but that's nothing compared to what
114 // boost::format is doing and may even be optimized away anyway.
115 static inline std::string fmtfloat(const char* fmt, double f)
116 {
117 char buf[20];
118 int ret = snprintf(buf, sizeof(buf), fmt, f);
119 if (ret < 0 || ret >= static_cast<int>(sizeof(buf))) {
120 return "?";
121 }
122 return std::string(buf, ret);
123 }
124
125 static inline void accountAuthLatency(uint64_t usec, int family)
126 {
127 if (family == AF_INET) {
128 g_stats.auth4Answers(usec);
129 g_stats.cumulativeAuth4Answers(usec);
130 } else {
131 g_stats.auth6Answers(usec);
132 g_stats.cumulativeAuth6Answers(usec);
133 }
134 }
135
136
137 SyncRes::SyncRes(const struct timeval& now) : d_authzonequeries(0), d_outqueries(0), d_tcpoutqueries(0), d_dotoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
138 d_totUsec(0), d_now(now),
139 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_qNameMinimization(s_qnameminimization), d_lm(s_lm)
140
141 {
142 }
143
144 static void allowAdditionalEntry(std::unordered_set<DNSName>& allowedAdditionals, const DNSRecord& rec);
145
146 void SyncRes::resolveAdditionals(const DNSName& qname, QType qtype, AdditionalMode mode, std::vector<DNSRecord>& additionals, unsigned int depth)
147 {
148 vector<DNSRecord> addRecords;
149
150 vState state = vState::Indeterminate;
151 switch (mode) {
152 case AdditionalMode::ResolveImmediately: {
153 set<GetBestNSAnswer> beenthere;
154 int res = doResolve(qname, qtype, addRecords, depth, beenthere, state);
155 if (res != 0) {
156 return;
157 }
158 // We're conservative here. We do not add Bogus records in any circumstance, we add Indeterminates only if no
159 // validation is required.
160 if (vStateIsBogus(state)) {
161 return;
162 }
163 if (shouldValidate() && state != vState::Secure && state != vState::Insecure) {
164 return;
165 }
166 for (auto& rec : addRecords) {
167 if (rec.d_place == DNSResourceRecord::ANSWER) {
168 additionals.push_back(std::move(rec));
169 }
170 }
171 break;
172 }
173 case AdditionalMode::CacheOnly:
174 case AdditionalMode::CacheOnlyRequireAuth: {
175 // Peek into cache
176 if (g_recCache->get(d_now.tv_sec, qname, qtype, mode == AdditionalMode::CacheOnlyRequireAuth, &addRecords, d_cacheRemote, false, d_routingTag, nullptr, nullptr, nullptr, &state) <= 0) {
177 return;
178 }
179 // See the comment for the ResolveImmediately case
180 if (vStateIsBogus(state)) {
181 return;
182 }
183 if (shouldValidate() && state != vState::Secure && state != vState::Insecure) {
184 return;
185 }
186 for (auto& rec : addRecords) {
187 if (rec.d_place == DNSResourceRecord::ANSWER) {
188 rec.d_ttl -= d_now.tv_sec ;
189 additionals.push_back(std::move(rec));
190 }
191 }
192 break;
193 }
194 case AdditionalMode::ResolveDeferred:
195 // FIXME: Not yet implemented
196 // Look in cache for authoritative answer, if available return it
197 // If not, look in nergache and submit if not there as well. The logic should be the same as
198 // #11294, which is in review atm.
199 break;
200 case AdditionalMode::Ignore:
201 break;
202 }
203 }
204
205 // The main (recursive) function to add additionals
206 // qtype: the original query type to expand
207 // start: records to start from
208 // This function uses to state sets to avoid infinite recursion and allow depulication
209 // depth is the main recursion depth
210 // additionaldepth is the depth for addAdditionals itself
211 void SyncRes::addAdditionals(QType qtype, const vector<DNSRecord>&start, vector<DNSRecord>&additionals, std::set<std::pair<DNSName, QType>>& uniqueCalls, std::set<std::tuple<DNSName, QType, QType>>& uniqueResults, unsigned int depth, unsigned additionaldepth)
212 {
213 if (additionaldepth >= 5 || start.empty()) {
214 return;
215 }
216
217 auto luaLocal = g_luaconfs.getLocal();
218 const auto it = luaLocal->allowAdditionalQTypes.find(qtype);
219 if (it == luaLocal->allowAdditionalQTypes.end()) {
220 return;
221 }
222 std::unordered_set<DNSName> addnames;
223 for (const auto& rec : start) {
224 if (rec.d_place == DNSResourceRecord::ANSWER) {
225 // currently, this function only knows about names, we could also take the target types that are dependent on
226 // record contents into account
227 // e.g. for NAPTR records, go only for SRV for flag value "s", or A/AAAA for flag value "a"
228 allowAdditionalEntry(addnames, rec);
229 }
230 }
231
232 // We maintain two sets for deduplication:
233 // - uniqueCalls makes sure we never resolve a qname/qtype twice
234 // - uniqueResults makes sure we never add the same qname/qytype RRSet to the result twice,
235 // but note that that set might contain multiple elements.
236
237 auto mode = it->second.second;
238 for (const auto& targettype : it->second.first) {
239 for (const auto& addname : addnames) {
240 std::vector<DNSRecord> records;
241 bool inserted = uniqueCalls.emplace(addname, targettype).second;
242 if (inserted) {
243 resolveAdditionals(addname, targettype, mode, records, depth);
244 }
245 if (!records.empty()) {
246 for (auto r = records.begin(); r != records.end(); ) {
247 QType covered = QType::ENT;
248 if (r->d_type == QType::RRSIG) {
249 if (auto rsig = getRR<RRSIGRecordContent>(*r); rsig != nullptr) {
250 covered = rsig->d_type;
251 }
252 }
253 if (uniqueResults.count(std::tuple(r->d_name, QType(r->d_type), covered)) > 0) {
254 // A bit expensive for vectors, but they are small
255 r = records.erase(r);
256 } else {
257 ++r;
258 }
259 }
260 for (const auto& r : records) {
261 additionals.push_back(r);
262 QType covered = QType::ENT;
263 if (r.d_type == QType::RRSIG) {
264 if (auto rsig = getRR<RRSIGRecordContent>(r); rsig != nullptr) {
265 covered = rsig->d_type;
266 }
267 }
268 uniqueResults.emplace(r.d_name, r.d_type, covered);
269 }
270 addAdditionals(targettype, records, additionals, uniqueCalls, uniqueResults, depth, additionaldepth + 1);
271 }
272 }
273 }
274 }
275
276 // The entry point for other code
277 void SyncRes::addAdditionals(QType qtype, vector<DNSRecord>&ret, unsigned int depth)
278 {
279 // The additional records of interest
280 std::vector<DNSRecord> additionals;
281
282 // We only call resolve for a specific name/type combo once
283 std::set<std::pair<DNSName, QType>> uniqueCalls;
284
285 // Collect multiple name/qtype from a single resolve but do not add a new set from new resolve calls
286 // For RRSIGs, the type covered is stored in the second Qtype
287 std::set<std::tuple<DNSName, QType, QType>> uniqueResults;
288
289 addAdditionals(qtype, ret, additionals, uniqueCalls, uniqueResults, depth, 0);
290
291 for (auto& rec : additionals) {
292 rec.d_place = DNSResourceRecord::ADDITIONAL;
293 ret.push_back(std::move(rec));
294 }
295 }
296
297 /** everything begins here - this is the entry point just after receiving a packet */
298 int SyncRes::beginResolve(const DNSName &qname, const QType qtype, QClass qclass, vector<DNSRecord>&ret, unsigned int depth)
299 {
300 d_eventTrace.add(RecEventTrace::SyncRes);
301 vState state = vState::Indeterminate;
302 s_queries++;
303 d_wasVariable=false;
304 d_wasOutOfBand=false;
305 d_cutStates.clear();
306
307 if (doSpecialNamesResolve(qname, qtype, qclass, ret)) {
308 d_queryValidationState = vState::Insecure; // this could fool our stats into thinking a validation took place
309 return 0; // so do check before updating counters (we do now)
310 }
311
312 auto qtypeCode = qtype.getCode();
313 /* rfc6895 section 3.1 */
314 if (qtypeCode == 0 || (qtypeCode >= 128 && qtypeCode <= 254) || qtypeCode == QType::RRSIG || qtypeCode == QType::NSEC3 || qtypeCode == QType::OPT || qtypeCode == 65535) {
315 return -1;
316 }
317
318 if(qclass==QClass::ANY)
319 qclass=QClass::IN;
320 else if(qclass!=QClass::IN)
321 return -1;
322
323 if (qtype == QType::DS) {
324 d_externalDSQuery = qname;
325 }
326 else {
327 d_externalDSQuery.clear();
328 }
329
330 set<GetBestNSAnswer> beenthere;
331 int res=doResolve(qname, qtype, ret, depth, beenthere, state);
332 d_queryValidationState = state;
333
334 if (shouldValidate()) {
335 if (d_queryValidationState != vState::Indeterminate) {
336 g_stats.dnssecValidations++;
337 }
338 auto xdnssec = g_xdnssec.getLocal();
339 if (xdnssec->check(qname)) {
340 increaseXDNSSECStateCounter(d_queryValidationState);
341 } else {
342 increaseDNSSECStateCounter(d_queryValidationState);
343 }
344 }
345
346 // Avoid calling addAdditionals() if we know we won't find anything
347 auto luaLocal = g_luaconfs.getLocal();
348 if (res == 0 && qclass == QClass::IN && luaLocal->allowAdditionalQTypes.find(qtype) != luaLocal->allowAdditionalQTypes.end()) {
349 addAdditionals(qtype, ret, depth);
350 }
351 d_eventTrace.add(RecEventTrace::SyncRes, res, false);
352 return res;
353 }
354
355 /*! Handles all special, built-in names
356 * Fills ret with an answer and returns true if it handled the query.
357 *
358 * Handles the following queries (and their ANY variants):
359 *
360 * - localhost. IN A
361 * - localhost. IN AAAA
362 * - 1.0.0.127.in-addr.arpa. IN PTR
363 * - 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. IN PTR
364 * - version.bind. CH TXT
365 * - version.pdns. CH TXT
366 * - id.server. CH TXT
367 * - trustanchor.server CH TXT
368 * - negativetrustanchor.server CH TXT
369 */
370 bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType qtype, const QClass qclass, vector<DNSRecord> &ret)
371 {
372 static const DNSName arpa("1.0.0.127.in-addr.arpa."), ip6_arpa("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."),
373 localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns."), trustanchorserver("trustanchor.server."),
374 negativetrustanchorserver("negativetrustanchor.server.");
375
376 bool handled = false;
377 vector<pair<QType::typeenum, string> > answers;
378
379 if ((qname == arpa || qname == ip6_arpa) &&
380 qclass == QClass::IN) {
381 handled = true;
382 if (qtype == QType::PTR || qtype == QType::ANY)
383 answers.emplace_back(QType::PTR, "localhost.");
384 }
385
386 if (qname.isPartOf(localhost) &&
387 qclass == QClass::IN) {
388 handled = true;
389 if (qtype == QType::A || qtype == QType::ANY)
390 answers.emplace_back(QType::A, "127.0.0.1");
391 if (qtype == QType::AAAA || qtype == QType::ANY)
392 answers.emplace_back(QType::AAAA, "::1");
393 }
394
395 if ((qname == versionbind || qname == idserver || qname == versionpdns) &&
396 qclass == QClass::CHAOS) {
397 handled = true;
398 if (qtype == QType::TXT || qtype == QType::ANY) {
399 if(qname == versionbind || qname == versionpdns)
400 answers.emplace_back(QType::TXT, "\"" + ::arg()["version-string"] + "\"");
401 else if (s_serverID != "disabled")
402 answers.emplace_back(QType::TXT, "\"" + s_serverID + "\"");
403 }
404 }
405
406 if (qname == trustanchorserver && qclass == QClass::CHAOS &&
407 ::arg().mustDo("allow-trust-anchor-query")) {
408 handled = true;
409 if (qtype == QType::TXT || qtype == QType::ANY) {
410 auto luaLocal = g_luaconfs.getLocal();
411 for (auto const &dsAnchor : luaLocal->dsAnchors) {
412 ostringstream ans;
413 ans<<"\"";
414 ans<<dsAnchor.first.toString(); // Explicit toString to have a trailing dot
415 for (auto const &dsRecord : dsAnchor.second) {
416 ans<<" ";
417 ans<<dsRecord.d_tag;
418 }
419 ans << "\"";
420 answers.emplace_back(QType::TXT, ans.str());
421 }
422 }
423 }
424
425 if (qname == negativetrustanchorserver && qclass == QClass::CHAOS &&
426 ::arg().mustDo("allow-trust-anchor-query")) {
427 handled = true;
428 if (qtype == QType::TXT || qtype == QType::ANY) {
429 auto luaLocal = g_luaconfs.getLocal();
430 for (auto const &negAnchor : luaLocal->negAnchors) {
431 ostringstream ans;
432 ans<<"\"";
433 ans<<negAnchor.first.toString(); // Explicit toString to have a trailing dot
434 if (negAnchor.second.length())
435 ans<<" "<<negAnchor.second;
436 ans << "\"";
437 answers.emplace_back(QType::TXT, ans.str());
438 }
439 }
440 }
441
442 if (handled && !answers.empty()) {
443 ret.clear();
444 d_wasOutOfBand=true;
445
446 DNSRecord dr;
447 dr.d_name = qname;
448 dr.d_place = DNSResourceRecord::ANSWER;
449 dr.d_class = qclass;
450 dr.d_ttl = 86400;
451 for (const auto& ans : answers) {
452 dr.d_type = ans.first;
453 dr.d_content = DNSRecordContent::mastermake(ans.first, qclass, ans.second);
454 ret.push_back(dr);
455 }
456 }
457
458 return handled;
459 }
460
461
462 //! This is the 'out of band resolver', in other words, the authoritative server
463 void SyncRes::AuthDomain::addSOA(std::vector<DNSRecord>& records) const
464 {
465 SyncRes::AuthDomain::records_t::const_iterator ziter = d_records.find(std::make_tuple(getName(), QType::SOA));
466 if (ziter != d_records.end()) {
467 DNSRecord dr = *ziter;
468 dr.d_place = DNSResourceRecord::AUTHORITY;
469 records.push_back(dr);
470 }
471 else {
472 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
473 }
474 }
475
476 int SyncRes::AuthDomain::getRecords(const DNSName& qname, const QType qtype, std::vector<DNSRecord>& records) const
477 {
478 int result = RCode::NoError;
479 records.clear();
480
481 // partial lookup
482 std::pair<records_t::const_iterator,records_t::const_iterator> range = d_records.equal_range(std::tie(qname));
483
484 SyncRes::AuthDomain::records_t::const_iterator ziter;
485 bool somedata = false;
486
487 for(ziter = range.first; ziter != range.second; ++ziter) {
488 somedata = true;
489
490 if(qtype == QType::ANY || ziter->d_type == qtype || ziter->d_type == QType::CNAME) {
491 // let rest of nameserver do the legwork on this one
492 records.push_back(*ziter);
493 }
494 else if (ziter->d_type == QType::NS && ziter->d_name.countLabels() > getName().countLabels()) {
495 // we hit a delegation point!
496 DNSRecord dr = *ziter;
497 dr.d_place=DNSResourceRecord::AUTHORITY;
498 records.push_back(dr);
499 }
500 }
501
502 if (!records.empty()) {
503 /* We have found an exact match, we're done */
504 // cerr<<qname<<": exact match in zone '"<<getName()<<"'"<<endl;
505 return result;
506 }
507
508 if (somedata) {
509 /* We have records for that name, but not of the wanted qtype */
510 // cerr<<qname<<": found record in '"<<getName()<<"', but nothing of the right type, sending SOA"<<endl;
511 addSOA(records);
512
513 return result;
514 }
515
516 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
517 DNSName wcarddomain(qname);
518 while(wcarddomain != getName() && wcarddomain.chopOff()) {
519 // cerr<<qname<<": trying '*."<<wcarddomain<<"' in "<<getName()<<endl;
520 range = d_records.equal_range(std::make_tuple(g_wildcarddnsname + wcarddomain));
521 if (range.first==range.second)
522 continue;
523
524 for(ziter = range.first; ziter != range.second; ++ziter) {
525 DNSRecord dr = *ziter;
526 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
527 if(dr.d_type == qtype || qtype == QType::ANY || dr.d_type == QType::CNAME) {
528 dr.d_name = qname;
529 dr.d_place = DNSResourceRecord::ANSWER;
530 records.push_back(dr);
531 }
532 }
533
534 if (records.empty()) {
535 addSOA(records);
536 }
537
538 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
539 return result;
540 }
541
542 /* Nothing for this name, no wildcard, let's see if there is some NS */
543 DNSName nsdomain(qname);
544 while (nsdomain.chopOff() && nsdomain != getName()) {
545 range = d_records.equal_range(std::make_tuple(nsdomain,QType::NS));
546 if(range.first == range.second)
547 continue;
548
549 for(ziter = range.first; ziter != range.second; ++ziter) {
550 DNSRecord dr = *ziter;
551 dr.d_place = DNSResourceRecord::AUTHORITY;
552 records.push_back(dr);
553 }
554 }
555
556 if(records.empty()) {
557 // cerr<<qname<<": no NS match in zone '"<<getName()<<"' either, handing out SOA"<<endl;
558 addSOA(records);
559 result = RCode::NXDomain;
560 }
561
562 return result;
563 }
564
565 bool SyncRes::doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType qtype, vector<DNSRecord>&ret, int& res)
566 {
567 d_authzonequeries++;
568 s_authzonequeries++;
569
570 res = domain.getRecords(qname, qtype, ret);
571 return true;
572 }
573
574 bool SyncRes::doOOBResolve(const DNSName &qname, const QType qtype, vector<DNSRecord>&ret, unsigned int depth, int& res)
575 {
576 string prefix;
577 if(doLog()) {
578 prefix=d_prefix;
579 prefix.append(depth, ' ');
580 }
581
582 DNSName authdomain(qname);
583 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
584 if(iter==t_sstorage.domainmap->end() || !iter->second.isAuth()) {
585 LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
586 return false;
587 }
588
589 LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
590 return doOOBResolve(iter->second, qname, qtype, ret, res);
591 }
592
593 bool SyncRes::isRecursiveForwardOrAuth(const DNSName &qname) const {
594 DNSName authname(qname);
595 domainmap_t::const_iterator iter = getBestAuthZone(&authname);
596 return iter != t_sstorage.domainmap->end() && (iter->second.isAuth() || iter->second.shouldRecurse());
597 }
598
599 bool SyncRes::isForwardOrAuth(const DNSName &qname) const {
600 DNSName authname(qname);
601 domainmap_t::const_iterator iter = getBestAuthZone(&authname);
602 return iter != t_sstorage.domainmap->end() && (iter->second.isAuth() || !iter->second.shouldRecurse());
603 }
604
605 uint64_t SyncRes::doEDNSDump(int fd)
606 {
607 int newfd = dup(fd);
608 if (newfd == -1) {
609 return 0;
610 }
611 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
612 if (!fp) {
613 close(newfd);
614 return 0;
615 }
616 uint64_t count = 0;
617
618 fprintf(fp.get(),"; edns from thread follows\n;\n");
619 for(const auto& eds : t_sstorage.ednsstatus) {
620 count++;
621 char tmp[26];
622 fprintf(fp.get(), "%s\t%d\t%s", eds.address.toString().c_str(), (int)eds.mode, ctime_r(&eds.modeSetAt, tmp));
623 }
624 return count;
625 }
626
627 uint64_t SyncRes::doDumpNSSpeeds(int fd)
628 {
629 int newfd = dup(fd);
630 if (newfd == -1) {
631 return 0;
632 }
633 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
634 if (!fp) {
635 close(newfd);
636 return 0;
637 }
638 fprintf(fp.get(), "; nsspeed dump from thread follows\n;\n");
639 uint64_t count=0;
640
641 for(const auto& i : t_sstorage.nsSpeeds)
642 {
643 count++;
644
645 // an <empty> can appear hear in case of authoritative (hosted) zones
646 fprintf(fp.get(), "%s -> ", i.first.toLogString().c_str());
647 for(const auto& j : i.second.d_collection)
648 {
649 // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
650 fprintf(fp.get(), "%s/%f ", j.first.toString().c_str(), j.second.peek());
651 }
652 fprintf(fp.get(), "\n");
653 }
654 return count;
655 }
656
657 uint64_t SyncRes::doDumpThrottleMap(int fd)
658 {
659 int newfd = dup(fd);
660 if (newfd == -1) {
661 return 0;
662 }
663 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
664 if (!fp) {
665 close(newfd);
666 return 0;
667 }
668 fprintf(fp.get(), "; throttle map dump follows\n");
669 fprintf(fp.get(), "; remote IP\tqname\tqtype\tcount\tttd\n");
670 uint64_t count=0;
671
672 const auto& throttleMap = t_sstorage.throttle.getThrottleMap();
673 for(const auto& i : throttleMap)
674 {
675 count++;
676 char tmp[26];
677 // remote IP, dns name, qtype, count, ttd
678 fprintf(fp.get(), "%s\t%s\t%d\t%u\t%s", std::get<0>(i.thing).toString().c_str(), std::get<1>(i.thing).toLogString().c_str(), std::get<2>(i.thing), i.count, ctime_r(&i.ttd, tmp));
679 }
680
681 return count;
682 }
683
684 uint64_t SyncRes::doDumpFailedServers(int fd)
685 {
686 int newfd = dup(fd);
687 if (newfd == -1) {
688 return 0;
689 }
690 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
691 if (!fp) {
692 close(newfd);
693 return 0;
694 }
695 fprintf(fp.get(), "; failed servers dump follows\n");
696 fprintf(fp.get(), "; remote IP\tcount\ttimestamp\n");
697 uint64_t count=0;
698
699 // We get a copy, so the I/O does not need to happen while holding the lock
700 for (const auto& i : s_fails.lock()->getMapCopy())
701 {
702 count++;
703 char tmp[26];
704 ctime_r(&i.last, tmp);
705 fprintf(fp.get(), "%s\t%llu\t%s", i.key.toString().c_str(), i.value, tmp);
706 }
707
708 return count;
709 }
710
711 uint64_t SyncRes::doDumpNonResolvingNS(int fd)
712 {
713 int newfd = dup(fd);
714 if (newfd == -1) {
715 return 0;
716 }
717 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
718 if (!fp) {
719 close(newfd);
720 return 0;
721 }
722 fprintf(fp.get(), "; non-resolving nameserver dump follows\n");
723 fprintf(fp.get(), "; name\tcount\ttimestamp\n");
724 uint64_t count=0;
725
726 // We get a copy, so the I/O does not need to happen while holding the lock
727 for (const auto& i : s_nonresolving.lock()->getMapCopy())
728 {
729 count++;
730 char tmp[26];
731 ctime_r(&i.last, tmp);
732 fprintf(fp.get(), "%s\t%llu\t%s", i.key.toString().c_str(), i.value, tmp);
733 }
734
735 return count;
736 }
737
738 /* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide
739 to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records
740 so that if there are RRSIGs for a name, we'll have them.
741
742 However, some hosts simply can't answer questions which ask for DNSSEC. This can manifest itself as:
743 * No answer
744 * FormErr
745 * Nonsense answer
746
747 The cause of "No answer" may be fragmentation, and it is tempting to probe if smaller answers would get through.
748 Another cause of "No answer" may simply be a network condition.
749 Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
750
751 Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
752 A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
753 clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
754 elsewhere. It may not have happened yet.
755
756 For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
757 */
758
759 LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, const DNSName& domain, const DNSName& auth, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult* res, bool* chained, const DNSName& nsName) const
760 {
761 /* what is your QUEST?
762 the goal is to get as many remotes as possible on the highest level of EDNS support
763 The levels are:
764
765 0) UNKNOWN Unknown state
766 1) EDNS: Honors EDNS0
767 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
768 3) NOEDNS: Generates FORMERR on EDNS queries
769
770 Everybody starts out assumed to be '0'.
771 If '0', send out EDNS0
772 If you FORMERR us, go to '3',
773 If no EDNS in response, go to '2'
774 If '1', send out EDNS0
775 If FORMERR, downgrade to 3
776 If '2', keep on including EDNS0, see what happens
777 Same behaviour as 0
778 If '3', send bare queries
779 */
780
781 auto ednsstatus = t_sstorage.ednsstatus.insert(ip).first; // does this include port? YES
782 auto &ind = t_sstorage.ednsstatus.get<ComboAddress>();
783 if (ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
784 t_sstorage.ednsstatus.reset(ind, ednsstatus);
785 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
786 }
787
788 const SyncRes::EDNSStatus::EDNSMode *mode = &ednsstatus->mode;
789 const SyncRes::EDNSStatus::EDNSMode oldmode = *mode;
790 int EDNSLevel = 0;
791 auto luaconfsLocal = g_luaconfs.getLocal();
792 ResolveContext ctx;
793 ctx.d_initialRequestId = d_initialRequestId;
794 ctx.d_nsName = nsName;
795 #ifdef HAVE_FSTRM
796 ctx.d_auth = auth;
797 #endif
798
799 LWResult::Result ret;
800 for(int tries = 0; tries < 3; ++tries) {
801 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
802
803 if (*mode == EDNSStatus::NOEDNS) {
804 g_stats.noEdnsOutQueries++;
805 EDNSLevel = 0; // level != mode
806 }
807 else if (ednsMANDATORY || *mode == EDNSStatus::UNKNOWN || *mode == EDNSStatus::EDNSOK || *mode == EDNSStatus::EDNSIGNORANT)
808 EDNSLevel = 1;
809
810 DNSName sendQname(domain);
811 if (g_lowercaseOutgoing)
812 sendQname.makeUsLowerCase();
813
814 if (d_asyncResolve) {
815 ret = d_asyncResolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, res, chained);
816 }
817 else {
818 ret = asyncresolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, d_outgoingProtobufServers, d_frameStreamServers, luaconfsLocal->outgoingProtobufExportConfig.exportTypes, res, chained);
819 }
820 // ednsstatus might be cleared, so do a new lookup
821 ednsstatus = t_sstorage.ednsstatus.insert(ip).first;
822 mode = &ednsstatus->mode;
823 if (ret == LWResult::Result::PermanentError || ret == LWResult::Result::OSLimitError || ret == LWResult::Result::Spoofed) {
824 return ret; // transport error, nothing to learn here
825 }
826
827 if (ret == LWResult::Result::Timeout) { // timeout, not doing anything with it now
828 return ret;
829 }
830 else if (*mode == EDNSStatus::UNKNOWN || *mode == EDNSStatus::EDNSOK || *mode == EDNSStatus::EDNSIGNORANT ) {
831 if(res->d_validpacket && !res->d_haveEDNS && res->d_rcode == RCode::FormErr) {
832 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
833 t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::NOEDNS);
834 continue;
835 }
836 else if(!res->d_haveEDNS) {
837 if (*mode != EDNSStatus::EDNSIGNORANT) {
838 t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSIGNORANT);
839 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 2"<<endl;
840 }
841 }
842 else {
843 t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSOK);
844 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
845 }
846 }
847
848 if (oldmode != *mode || !ednsstatus->modeSetAt) {
849 t_sstorage.ednsstatus.setTS(ind, ednsstatus, d_now.tv_sec);
850 }
851 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
852 return LWResult::Result::Success;
853 }
854 return ret;
855 }
856
857 #define QLOG(x) LOG(prefix << " child=" << child << ": " << x << endl)
858
859 /* The parameters from rfc9156. */
860 /* maximum number of QNAME minimisation iterations */
861 static const unsigned int s_max_minimise_count = 10;
862 /* number of queries that should only have one label appended */
863 static const unsigned int s_minimise_one_lab = 4;
864
865 static unsigned int qmStepLen(unsigned int labels, unsigned int qnamelen, unsigned int i)
866 {
867 unsigned int step;
868
869 if (i < s_minimise_one_lab) {
870 step = 1;
871 } else if (i < s_max_minimise_count) {
872 step = std::max(1U, (qnamelen - labels) / (10 - i));
873 } else {
874 step = qnamelen - labels;
875 }
876 unsigned int targetlen = std::min(labels + step, qnamelen);
877 return targetlen;
878 }
879
880 int SyncRes::doResolve(const DNSName &qname, const QType qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state) {
881
882 string prefix = d_prefix;
883 prefix.append(depth, ' ');
884 auto luaconfsLocal = g_luaconfs.getLocal();
885
886 /* Apply qname (including CNAME chain) filtering policies */
887 if (d_wantsRPZ && !d_appliedPolicy.wasHit()) {
888 if (luaconfsLocal->dfe.getQueryPolicy(qname, d_discardedPolicies, d_appliedPolicy)) {
889 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
890 bool done = false;
891 int rcode = RCode::NoError;
892 handlePolicyHit(prefix, qname, qtype, ret, done, rcode, depth);
893 if (done) {
894 return rcode;
895 }
896 }
897 }
898
899 initZoneCutsFromTA(qname);
900
901 // In the auth or recursive forward case, it does not make sense to do qname-minimization
902 if (!getQNameMinimization() || isRecursiveForwardOrAuth(qname)) {
903 return doResolveNoQNameMinimization(qname, qtype, ret, depth, beenthere, state);
904 }
905
906 // The qname minimization algorithm is a simplified version of the one in RFC 7816 (bis).
907 // It could be simplified because the cache maintenance (both positive and negative)
908 // is already done by doResolveNoQNameMinimization().
909 //
910 // Sketch of algorithm:
911 // Check cache
912 // If result found: done
913 // Otherwise determine closes ancestor from cache data
914 // Repeat querying A, adding more labels of the original qname
915 // If we get a delegation continue at ancestor determination
916 // Until we have the full name.
917 //
918 // The algorithm starts with adding a single label per iteration, and
919 // moves to three labels per iteration after three iterations.
920
921 DNSName child;
922 prefix.append(string("QM ") + qname.toString() + "|" + qtype.toString());
923
924 QLOG("doResolve");
925
926 // Look in cache only
927 vector<DNSRecord> retq;
928 bool old = setCacheOnly(true);
929 bool fromCache = false;
930 // For cache peeking, we tell doResolveNoQNameMinimization not to consider the (non-recursive) forward case.
931 // Otherwise all queries in a forward domain will be forwarded, while we want to consult the cache.
932 // The out-of-band cases for doResolveNoQNameMinimization() should be reconsidered and redone some day.
933 int res = doResolveNoQNameMinimization(qname, qtype, retq, depth, beenthere, state, &fromCache, nullptr, false);
934 setCacheOnly(old);
935 if (fromCache) {
936 QLOG("Step0 Found in cache");
937 if (d_appliedPolicy.d_type != DNSFilterEngine::PolicyType::None && (d_appliedPolicy.d_kind == DNSFilterEngine::PolicyKind::NXDOMAIN || d_appliedPolicy.d_kind == DNSFilterEngine::PolicyKind::NODATA)) {
938 ret.clear();
939 }
940 ret.insert(ret.end(), retq.begin(), retq.end());
941
942 return res;
943 }
944 QLOG("Step0 Not cached");
945
946 const unsigned int qnamelen = qname.countLabels();
947
948 DNSName fwdomain(qname);
949 const bool forwarded = getBestAuthZone(&fwdomain) != t_sstorage.domainmap->end();
950 if (forwarded) {
951 QLOG("Step0 qname is in a forwarded domain " << fwdomain);
952 }
953
954 for (unsigned int i = 0; i <= qnamelen; ) {
955
956 // Step 1
957 vector<DNSRecord> bestns;
958 DNSName nsdomain(qname);
959 if (qtype == QType::DS) {
960 nsdomain.chopOff();
961 }
962 // the two retries allow getBestNSFromCache&co to reprime the root
963 // hints, in case they ever go missing
964 for (int tries = 0; tries < 2 && bestns.empty(); ++tries) {
965 bool flawedNSSet = false;
966 set<GetBestNSAnswer> beenthereIgnored;
967 getBestNSFromCache(nsdomain, qtype, bestns, &flawedNSSet, depth, beenthereIgnored, boost::make_optional(forwarded, fwdomain));
968 if (forwarded) {
969 break;
970 }
971 }
972
973 if (bestns.size() == 0) {
974 if (!forwarded) {
975 // Something terrible is wrong
976 QLOG("Step1 No ancestor found return ServFail");
977 return RCode::ServFail;
978 }
979 child = fwdomain;
980 } else {
981 QLOG("Step1 Ancestor from cache is " << bestns[0].d_name);
982 if (forwarded) {
983 child = bestns[0].d_name.isPartOf(fwdomain) ? bestns[0].d_name : fwdomain;
984 QLOG("Step1 Final Ancestor (using forwarding info) is " << child);
985 } else {
986 child = bestns[0].d_name;
987 }
988 }
989 for (; i <= qnamelen; i++) {
990 // Step 2
991 unsigned int labels = child.countLabels();
992 unsigned int targetlen = qmStepLen(labels, qnamelen, i);
993
994 while (labels < targetlen) {
995 child.prependRawLabel(qname.getRawLabel(qnamelen - labels - 1));
996 labels++;
997 }
998 // rfc9156 section-2.3, append labels if they start with an underscore
999 while (labels < qnamelen) {
1000 auto prependLabel = qname.getRawLabel(qnamelen - labels - 1);
1001 if (prependLabel.at(0) != '_') {
1002 break;
1003 }
1004 child.prependRawLabel(prependLabel);
1005 labels++;
1006 }
1007
1008 QLOG("Step2 New child");
1009
1010 // Step 3 resolve
1011 if (child == qname) {
1012 QLOG("Step3 Going to do final resolve");
1013 res = doResolveNoQNameMinimization(qname, qtype, ret, depth, beenthere, state);
1014 QLOG("Step3 Final resolve: " << RCode::to_s(res) << "/" << ret.size());
1015 return res;
1016 }
1017
1018 // Step 4
1019 QLOG("Step4 Resolve A for child");
1020 bool oldFollowCNAME = d_followCNAME;
1021 d_followCNAME = false;
1022 retq.resize(0);
1023 StopAtDelegation stopAtDelegation = Stop;
1024 res = doResolveNoQNameMinimization(child, QType::A, retq, depth, beenthere, state, nullptr, &stopAtDelegation);
1025 d_followCNAME = oldFollowCNAME;
1026 QLOG("Step4 Resolve A result is " << RCode::to_s(res) << "/" << retq.size() << "/" << stopAtDelegation);
1027 if (stopAtDelegation == Stopped) {
1028 QLOG("Delegation seen, continue at step 1");
1029 break;
1030 }
1031
1032 if (res != RCode::NoError) {
1033 // Case 5: unexpected answer
1034 QLOG("Step5: other rcode, last effort final resolve");
1035 setQNameMinimization(false);
1036 // We might have hit a depth level check, but we still want to allow some recursion levels in the fallback
1037 // no-qname-minimization case. This has the effect that a qname minimization fallback case might reach 150% of
1038 // maxdepth.
1039 res = doResolveNoQNameMinimization(qname, qtype, ret, depth/2, beenthere, state);
1040
1041 if(res == RCode::NoError) {
1042 s_qnameminfallbacksuccess++;
1043 }
1044
1045 QLOG("Step5 End resolve: " << RCode::to_s(res) << "/" << ret.size());
1046 return res;
1047 }
1048 }
1049 }
1050
1051 // Should not be reached
1052 QLOG("Max iterations reached, return ServFail");
1053 return RCode::ServFail;
1054 }
1055
1056 /*! This function will check the cache and go out to the internet if the answer is not in cache
1057 *
1058 * \param qname The name we need an answer for
1059 * \param qtype
1060 * \param ret The vector of DNSRecords we need to fill with the answers
1061 * \param depth The recursion depth we are in
1062 * \param beenthere
1063 * \param fromCache tells the caller the result came from the cache, may be nullptr
1064 * \param stopAtDelegation if non-nullptr and pointed-to value is Stop requests the callee to stop at a delegation, if so pointed-to value is set to Stopped
1065 * \return DNS RCODE or -1 (Error)
1066 */
1067 int SyncRes::doResolveNoQNameMinimization(const DNSName &qname, const QType qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state, bool *fromCache, StopAtDelegation *stopAtDelegation, bool considerforwards)
1068 {
1069 string prefix;
1070 if(doLog()) {
1071 prefix=d_prefix;
1072 prefix.append(depth, ' ');
1073 }
1074
1075 LOG(prefix<<qname<<": Wants "<< (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing, "<<(d_requireAuthData ? "" : "NO ")<<"auth data in query for "<<qtype<<endl);
1076
1077 if (s_maxdepth && depth > s_maxdepth) {
1078 string msg = "More than " + std::to_string(s_maxdepth) + " (max-recursion-depth) levels of recursion needed while resolving " + qname.toLogString();
1079 LOG(prefix << qname << ": " << msg << endl);
1080 throw ImmediateServFailException(msg);
1081 }
1082 int res=0;
1083
1084 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
1085 if(!(d_updatingRootNS && qtype.getCode()==QType::NS && qname.isRoot())) {
1086 if(d_cacheonly) { // very limited OOB support
1087 LWResult lwr;
1088 LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype<<"', peeking at auth/forward zones"<<endl);
1089 DNSName authname(qname);
1090 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
1091 if(iter != t_sstorage.domainmap->end()) {
1092 if(iter->second.isAuth()) {
1093 ret.clear();
1094 d_wasOutOfBand = doOOBResolve(qname, qtype, ret, depth, res);
1095 if (fromCache)
1096 *fromCache = d_wasOutOfBand;
1097 return res;
1098 }
1099 else if (considerforwards) {
1100 const vector<ComboAddress>& servers = iter->second.d_servers;
1101 const ComboAddress remoteIP = servers.front();
1102 LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
1103
1104 boost::optional<Netmask> nm;
1105 bool chained = false;
1106 // forwardes are "anonymous", so plug in an empty name; some day we might have a fancier config language...
1107 auto resolveRet = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, authname, qtype.getCode(), false, false, &d_now, nm, &lwr, &chained, DNSName());
1108
1109 d_totUsec += lwr.d_usec;
1110 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
1111 if (fromCache)
1112 *fromCache = true;
1113
1114 // filter out the good stuff from lwr.result()
1115 if (resolveRet == LWResult::Result::Success) {
1116 for(const auto& rec : lwr.d_records) {
1117 if(rec.d_place == DNSResourceRecord::ANSWER)
1118 ret.push_back(rec);
1119 }
1120 return 0;
1121 }
1122 else {
1123 return RCode::ServFail;
1124 }
1125 }
1126 }
1127 }
1128
1129 DNSName authname(qname);
1130 bool wasForwardedOrAuthZone = false;
1131 bool wasAuthZone = false;
1132 bool wasForwardRecurse = false;
1133 domainmap_t::const_iterator iter = getBestAuthZone(&authname);
1134 if(iter != t_sstorage.domainmap->end()) {
1135 const auto& domain = iter->second;
1136 wasForwardedOrAuthZone = true;
1137
1138 if (domain.isAuth()) {
1139 wasAuthZone = true;
1140 } else if (domain.shouldRecurse()) {
1141 wasForwardRecurse = true;
1142 }
1143 }
1144
1145 /* When we are looking for a DS, we want to the non-CNAME cache check first
1146 because we can actually have a DS (from the parent zone) AND a CNAME (from
1147 the child zone), and what we really want is the DS */
1148 if (qtype != QType::DS && doCNAMECacheCheck(qname, qtype, ret, depth, res, state, wasAuthZone, wasForwardRecurse)) { // will reroute us if needed
1149 d_wasOutOfBand = wasAuthZone;
1150 // Here we have an issue. If we were prevented from going out to the network (cache-only was set, possibly because we
1151 // are in QM Step0) we might have a CNAME but not the corresponding target.
1152 // It means that we will sometimes go to the next steps when we are in fact done, but that's fine since
1153 // we will get the records from the cache, resulting in a small overhead.
1154 // This might be a real problem if we had a RPZ hit, though, because we do not want the processing to continue, since
1155 // RPZ rules will not be evaluated anymore (we already matched).
1156 const bool stoppedByPolicyHit = d_appliedPolicy.wasHit();
1157
1158 if (fromCache && (!d_cacheonly || stoppedByPolicyHit)) {
1159 *fromCache = true;
1160 }
1161 /* Apply Post filtering policies */
1162
1163 if (d_wantsRPZ && !stoppedByPolicyHit) {
1164 auto luaLocal = g_luaconfs.getLocal();
1165 if (luaLocal->dfe.getPostPolicy(ret, d_discardedPolicies, d_appliedPolicy)) {
1166 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
1167 bool done = false;
1168 handlePolicyHit(prefix, qname, qtype, ret, done, res, depth);
1169 if (done && fromCache) {
1170 *fromCache = true;
1171 }
1172 }
1173 }
1174
1175 return res;
1176 }
1177
1178 if (doCacheCheck(qname, authname, wasForwardedOrAuthZone, wasAuthZone, wasForwardRecurse, qtype, ret, depth, res, state)) {
1179 // we done
1180 d_wasOutOfBand = wasAuthZone;
1181 if (fromCache) {
1182 *fromCache = true;
1183 }
1184
1185 if (d_wantsRPZ && !d_appliedPolicy.wasHit()) {
1186 auto luaLocal = g_luaconfs.getLocal();
1187 if (luaLocal->dfe.getPostPolicy(ret, d_discardedPolicies, d_appliedPolicy)) {
1188 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
1189 bool done = false;
1190 handlePolicyHit(prefix, qname, qtype, ret, done, res, depth);
1191 }
1192 }
1193
1194 return res;
1195 }
1196
1197 /* if we have not found a cached DS (or denial of), now is the time to look for a CNAME */
1198 if (qtype == QType::DS && doCNAMECacheCheck(qname, qtype, ret, depth, res, state, wasAuthZone, wasForwardRecurse)) { // will reroute us if needed
1199 d_wasOutOfBand = wasAuthZone;
1200 // Here we have an issue. If we were prevented from going out to the network (cache-only was set, possibly because we
1201 // are in QM Step0) we might have a CNAME but not the corresponding target.
1202 // It means that we will sometimes go to the next steps when we are in fact done, but that's fine since
1203 // we will get the records from the cache, resulting in a small overhead.
1204 // This might be a real problem if we had a RPZ hit, though, because we do not want the processing to continue, since
1205 // RPZ rules will not be evaluated anymore (we already matched).
1206 const bool stoppedByPolicyHit = d_appliedPolicy.wasHit();
1207
1208 if (fromCache && (!d_cacheonly || stoppedByPolicyHit)) {
1209 *fromCache = true;
1210 }
1211 /* Apply Post filtering policies */
1212
1213 if (d_wantsRPZ && !stoppedByPolicyHit) {
1214 auto luaLocal = g_luaconfs.getLocal();
1215 if (luaLocal->dfe.getPostPolicy(ret, d_discardedPolicies, d_appliedPolicy)) {
1216 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
1217 bool done = false;
1218 handlePolicyHit(prefix, qname, qtype, ret, done, res, depth);
1219 if (done && fromCache) {
1220 *fromCache = true;
1221 }
1222 }
1223 }
1224
1225 return res;
1226 }
1227 }
1228
1229 if (d_cacheonly) {
1230 return 0;
1231 }
1232
1233 LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype<<"', trying to find an appropriate NS record"<<endl);
1234
1235 DNSName subdomain(qname);
1236 if (qtype == QType::DS) subdomain.chopOff();
1237
1238 NsSet nsset;
1239 bool flawedNSSet=false;
1240
1241 // the two retries allow getBestNSNamesFromCache&co to reprime the root
1242 // hints, in case they ever go missing
1243 for(int tries=0;tries<2 && nsset.empty();++tries) {
1244 subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
1245 }
1246
1247 res = doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state, stopAtDelegation);
1248
1249 /* Apply Post filtering policies */
1250 if (d_wantsRPZ && !d_appliedPolicy.wasHit()) {
1251 auto luaLocal = g_luaconfs.getLocal();
1252 if (luaLocal->dfe.getPostPolicy(ret, d_discardedPolicies, d_appliedPolicy)) {
1253 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
1254 bool done = false;
1255 handlePolicyHit(prefix, qname, qtype, ret, done, res, depth);
1256 }
1257 }
1258
1259 if (!res) {
1260 return 0;
1261 }
1262
1263 LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
1264
1265 return res<0 ? RCode::ServFail : res;
1266 }
1267
1268 #if 0
1269 // for testing purposes
1270 static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
1271 {
1272 return !(a.sin4.sin_family < a.sin4.sin_family);
1273 }
1274 #endif
1275
1276 struct speedOrderCA
1277 {
1278 speedOrderCA(std::map<ComboAddress,float>& speeds): d_speeds(speeds) {}
1279 bool operator()(const ComboAddress& a, const ComboAddress& b) const
1280 {
1281 return d_speeds[a] < d_speeds[b];
1282 }
1283 std::map<ComboAddress, float>& d_speeds;
1284 };
1285
1286 /** This function explicitly goes out for A or AAAA addresses
1287 */
1288 vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS)
1289 {
1290 typedef vector<DNSRecord> res_t;
1291 typedef vector<ComboAddress> ret_t;
1292 ret_t ret;
1293
1294 bool oldCacheOnly = setCacheOnly(cacheOnly);
1295 bool oldRequireAuthData = d_requireAuthData;
1296 bool oldValidationRequested = d_DNSSECValidationRequested;
1297 bool oldFollowCNAME = d_followCNAME;
1298 bool seenV6 = false;
1299 const unsigned int startqueries = d_outqueries;
1300 d_requireAuthData = false;
1301 d_DNSSECValidationRequested = false;
1302 d_followCNAME = true;
1303
1304 try {
1305 // First look for both A and AAAA in the cache
1306 res_t cset;
1307 if (s_doIPv4 && g_recCache->get(d_now.tv_sec, qname, QType::A, false, &cset, d_cacheRemote, false, d_routingTag) > 0) {
1308 for (const auto &i : cset) {
1309 if (auto rec = getRR<ARecordContent>(i)) {
1310 ret.push_back(rec->getCA(53));
1311 }
1312 }
1313 }
1314 if (s_doIPv6 && g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, false, d_routingTag) > 0) {
1315 for (const auto &i : cset) {
1316 if (auto rec = getRR<AAAARecordContent>(i)) {
1317 seenV6 = true;
1318 ret.push_back(rec->getCA(53));
1319 }
1320 }
1321 }
1322 if (ret.empty()) {
1323 // Neither A nor AAAA in the cache...
1324 vState newState = vState::Indeterminate;
1325 cset.clear();
1326 // Go out to get A's
1327 if (s_doIPv4 && doResolve(qname, QType::A, cset, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out
1328 for (auto const &i : cset) {
1329 if (i.d_type == QType::A) {
1330 if (auto rec = getRR<ARecordContent>(i)) {
1331 ret.push_back(rec->getCA(53));
1332 }
1333 }
1334 }
1335 }
1336 if (s_doIPv6) { // s_doIPv6 **IMPLIES** pdns::isQueryLocalAddressFamilyEnabled(AF_INET6) returned true
1337 if (ret.empty()) {
1338 // We only go out immediately to find IPv6 records if we did not find any IPv4 ones.
1339 newState = vState::Indeterminate;
1340 cset.clear();
1341 if (doResolve(qname, QType::AAAA, cset, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out
1342 for (const auto &i : cset) {
1343 if (i.d_type == QType::AAAA) {
1344 if (auto rec = getRR<AAAARecordContent>(i)) {
1345 seenV6 = true;
1346 ret.push_back(rec->getCA(53));
1347 }
1348 }
1349 }
1350 }
1351 } else {
1352 // We have some IPv4 records, consult the cache, we might have encountered some IPv6 glue
1353 cset.clear();
1354 if (g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, false, d_routingTag) > 0) {
1355 for (const auto &i : cset) {
1356 if (auto rec = getRR<AAAARecordContent>(i)) {
1357 seenV6 = true;
1358 ret.push_back(rec->getCA(53));
1359 }
1360 }
1361 }
1362 }
1363 }
1364 }
1365 if (s_doIPv6 && !seenV6 && !cacheOnly) {
1366 // No IPv6 records in cache, check negcache and submit async task if negache does not have the data
1367 // so that the next time the cache or the negcache will have data
1368 NegCache::NegCacheEntry ne;
1369 bool inNegCache = g_negCache->get(qname, QType::AAAA, d_now, ne, true);
1370 if (!inNegCache) {
1371 pushResolveTask(qname, QType::AAAA, d_now.tv_sec, d_now.tv_sec + 60);
1372 }
1373 }
1374 }
1375 catch (const PolicyHitException&) {
1376 // We ignore a policy hit while trying to retrieve the addresses
1377 // of a NS and keep processing the current query
1378 }
1379
1380 if (ret.empty() && d_outqueries > startqueries) {
1381 // We did 1 or more outgoing queries to resolve this NS name but returned empty handed
1382 addressQueriesForNS++;
1383 }
1384 d_requireAuthData = oldRequireAuthData;
1385 d_DNSSECValidationRequested = oldValidationRequested;
1386 setCacheOnly(oldCacheOnly);
1387 d_followCNAME = oldFollowCNAME;
1388
1389 /* we need to remove from the nsSpeeds collection the existing IPs
1390 for this nameserver that are no longer in the set, even if there
1391 is only one or none at all in the current set.
1392 */
1393 map<ComboAddress, float> speeds;
1394 auto& collection = t_sstorage.nsSpeeds[qname];
1395 float factor = collection.getFactor(d_now);
1396 for(const auto& val: ret) {
1397 speeds[val] = collection.d_collection[val].get(factor);
1398 }
1399
1400 t_sstorage.nsSpeeds[qname].purge(speeds);
1401
1402 if (ret.size() > 1) {
1403 shuffle(ret.begin(), ret.end(), pdns::dns_random_engine());
1404 speedOrderCA so(speeds);
1405 stable_sort(ret.begin(), ret.end(), so);
1406 }
1407
1408 if(doLog()) {
1409 string prefix=d_prefix;
1410 prefix.append(depth, ' ');
1411 LOG(prefix<<"Nameserver "<<qname<<" IPs: ");
1412 bool first = true;
1413 for(const auto& addr : ret) {
1414 if (first) {
1415 first = false;
1416 }
1417 else {
1418 LOG(", ");
1419 }
1420 LOG((addr.toString())<<"(" << fmtfloat("%0.2f", speeds[addr]/1000.0) <<"ms)");
1421 }
1422 LOG(endl);
1423 }
1424
1425 return ret;
1426 }
1427
1428 void SyncRes::getBestNSFromCache(const DNSName &qname, const QType qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere, const boost::optional<DNSName>& cutOffDomain)
1429 {
1430 string prefix;
1431 DNSName subdomain(qname);
1432 if(doLog()) {
1433 prefix=d_prefix;
1434 prefix.append(depth, ' ');
1435 }
1436 bestns.clear();
1437 bool brokeloop;
1438 do {
1439 if (cutOffDomain && (subdomain == *cutOffDomain || !subdomain.isPartOf(*cutOffDomain))) {
1440 break;
1441 }
1442 brokeloop=false;
1443 LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
1444 vector<DNSRecord> ns;
1445 *flawedNSSet = false;
1446
1447 if(g_recCache->get(d_now.tv_sec, subdomain, QType::NS, false, &ns, d_cacheRemote, false, d_routingTag) > 0) {
1448 bestns.reserve(ns.size());
1449
1450 for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
1451 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
1452 vector<DNSRecord> aset;
1453 QType nsqt{QType::ADDR};
1454 if (s_doIPv4 && !s_doIPv6) {
1455 nsqt = QType::A;
1456 } else if (!s_doIPv4 && s_doIPv6) {
1457 nsqt = QType::AAAA;
1458 }
1459
1460 const DNSRecord& dr=*k;
1461 auto nrr = getRR<NSRecordContent>(dr);
1462 if(nrr && (!nrr->getNS().isPartOf(subdomain) || g_recCache->get(d_now.tv_sec, nrr->getNS(), nsqt,
1463 false, doLog() ? &aset : 0, d_cacheRemote, false, d_routingTag) > 5)) {
1464 bestns.push_back(dr);
1465 LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<nrr->getNS()<<"'"<<endl);
1466 LOG(prefix<<qname<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
1467 if(!aset.empty()) {
1468 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
1469 }
1470 else {
1471 LOG(", not in cache / did not look at cache"<<endl);
1472 }
1473 }
1474 else {
1475 *flawedNSSet=true;
1476 LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
1477 }
1478 }
1479 }
1480
1481 if(!bestns.empty()) {
1482 GetBestNSAnswer answer;
1483 answer.qname=qname;
1484 answer.qtype=qtype.getCode();
1485 for(const auto& dr : bestns) {
1486 if (auto nsContent = getRR<NSRecordContent>(dr)) {
1487 answer.bestns.emplace(dr.d_name, nsContent->getNS());
1488 }
1489 }
1490
1491 auto insertionPair = beenthere.insert(std::move(answer));
1492 if(!insertionPair.second) {
1493 brokeloop=true;
1494 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
1495 ;
1496 if(doLog())
1497 for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
1498 bool neo = (j == insertionPair.first);
1499 LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
1500 }
1501 bestns.clear();
1502 }
1503 else {
1504 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
1505 return;
1506 }
1507 }
1508 }
1509 LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
1510
1511 if(subdomain.isRoot() && !brokeloop) {
1512 // We lost the root NS records
1513 primeHints();
1514 LOG(prefix<<qname<<": reprimed the root"<<endl);
1515 /* let's prevent an infinite loop */
1516 if (!d_updatingRootNS) {
1517 primeRootNSZones(g_dnssecmode, depth);
1518 getRootNS(d_now, d_asyncResolve, depth);
1519 }
1520 }
1521 } while(subdomain.chopOff());
1522 }
1523
1524 SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) const
1525 {
1526 if (t_sstorage.domainmap->empty()) {
1527 return t_sstorage.domainmap->end();
1528 }
1529
1530 SyncRes::domainmap_t::const_iterator ret;
1531 do {
1532 ret=t_sstorage.domainmap->find(*qname);
1533 if(ret!=t_sstorage.domainmap->end())
1534 break;
1535 }while(qname->chopOff());
1536 return ret;
1537 }
1538
1539 /** doesn't actually do the work, leaves that to getBestNSFromCache */
1540 DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere)
1541 {
1542 string prefix;
1543 if (doLog()) {
1544 prefix = d_prefix;
1545 prefix.append(depth, ' ');
1546 }
1547 DNSName authOrForwDomain(qname);
1548
1549 domainmap_t::const_iterator iter = getBestAuthZone(&authOrForwDomain);
1550 // We have an auth, forwarder of forwarder-recurse
1551 if (iter != t_sstorage.domainmap->end()) {
1552 if (iter->second.isAuth()) {
1553 // this gets picked up in doResolveAt, the empty DNSName, combined with the
1554 // empty vector means 'we are auth for this zone'
1555 nsset.insert({DNSName(), {{}, false}});
1556 return authOrForwDomain;
1557 }
1558 else {
1559 if (iter->second.shouldRecurse()) {
1560 // Again, picked up in doResolveAt. An empty DNSName, combined with a
1561 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
1562 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
1563 nsset.insert({DNSName(), {iter->second.d_servers, true }});
1564 return authOrForwDomain;
1565 }
1566 }
1567 }
1568
1569 // We might have a (non-recursive) forwarder, but maybe the cache already contains
1570 // a better NS
1571 vector<DNSRecord> bestns;
1572 DNSName nsFromCacheDomain(g_rootdnsname);
1573 getBestNSFromCache(qname, qtype, bestns, flawedNSSet, depth, beenthere);
1574
1575 // Pick up the auth domain
1576 for (const auto& k : bestns) {
1577 const auto nsContent = getRR<NSRecordContent>(k);
1578 if (nsContent) {
1579 nsFromCacheDomain = k.d_name;
1580 break;
1581 }
1582 }
1583
1584 if (iter != t_sstorage.domainmap->end()) {
1585 if (doLog()) {
1586 LOG(prefix << qname << " authOrForwDomain: " << authOrForwDomain << " nsFromCacheDomain: " << nsFromCacheDomain << " isPartof: " << authOrForwDomain.isPartOf(nsFromCacheDomain) << endl);
1587 }
1588
1589 // If the forwarder is better or equal to what's found in the cache, use forwarder. Note that name.isPartOf(name).
1590 // So queries that get NS for authOrForwDomain itself go to the forwarder
1591 if (authOrForwDomain.isPartOf(nsFromCacheDomain)) {
1592 if (doLog()) {
1593 LOG(prefix << qname << ": using forwarder as NS" << endl);
1594 }
1595 nsset.insert({DNSName(), {iter->second.d_servers, false }});
1596 return authOrForwDomain;
1597 } else {
1598 if (doLog()) {
1599 LOG(prefix << qname << ": using NS from cache" << endl);
1600 }
1601 }
1602 }
1603 for (auto k = bestns.cbegin(); k != bestns.cend(); ++k) {
1604 // The actual resolver code will not even look at the ComboAddress or bool
1605 const auto nsContent = getRR<NSRecordContent>(*k);
1606 if (nsContent) {
1607 nsset.insert({nsContent->getNS(), {{}, false}});
1608 }
1609 }
1610 return nsFromCacheDomain;
1611 }
1612
1613 void SyncRes::updateValidationStatusInCache(const DNSName &qname, const QType qt, bool aa, vState newState) const
1614 {
1615 if (qt == QType::ANY || qt == QType::ADDR) {
1616 // not doing that
1617 return;
1618 }
1619
1620 if (vStateIsBogus(newState)) {
1621 g_recCache->updateValidationStatus(d_now.tv_sec, qname, qt, d_cacheRemote, d_routingTag, aa, newState, s_maxbogusttl + d_now.tv_sec);
1622 }
1623 else {
1624 g_recCache->updateValidationStatus(d_now.tv_sec, qname, qt, d_cacheRemote, d_routingTag, aa, newState, boost::none);
1625 }
1626 }
1627
1628 static bool scanForCNAMELoop(const DNSName& name, const vector<DNSRecord>& records)
1629 {
1630 for (const auto& record: records) {
1631 if (record.d_type == QType::CNAME && record.d_place == DNSResourceRecord::ANSWER) {
1632 if (name == record.d_name) {
1633 return true;
1634 }
1635 }
1636 }
1637 return false;
1638 }
1639
1640 bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType qtype, vector<DNSRecord>& ret, unsigned int depth, int &res, vState& state, bool wasAuthZone, bool wasForwardRecurse)
1641 {
1642 string prefix;
1643 if(doLog()) {
1644 prefix=d_prefix;
1645 prefix.append(depth, ' ');
1646 }
1647
1648 if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
1649 LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
1650 res=RCode::ServFail;
1651 return true;
1652 }
1653
1654 vector<DNSRecord> cset;
1655 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
1656 vector<std::shared_ptr<DNSRecord>> authorityRecs;
1657 bool wasAuth;
1658 uint32_t capTTL = std::numeric_limits<uint32_t>::max();
1659 DNSName foundName;
1660 DNSName authZone;
1661 QType foundQT = QType::ENT;
1662
1663 /* we don't require auth data for forward-recurse lookups */
1664 if (g_recCache->get(d_now.tv_sec, qname, QType::CNAME, !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_refresh, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth, &authZone, &d_fromAuthIP) > 0) {
1665 foundName = qname;
1666 foundQT = QType::CNAME;
1667 }
1668
1669 if (foundName.empty() && qname != g_rootdnsname) {
1670 // look for a DNAME cache hit
1671 auto labels = qname.getRawLabels();
1672 DNSName dnameName(g_rootdnsname);
1673
1674 do {
1675 dnameName.prependRawLabel(labels.back());
1676 labels.pop_back();
1677 if (dnameName == qname && qtype != QType::DNAME) { // The client does not want a DNAME, but we've reached the QNAME already. So there is no match
1678 break;
1679 }
1680 if (g_recCache->get(d_now.tv_sec, dnameName, QType::DNAME, !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_refresh, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth, &authZone, &d_fromAuthIP) > 0) {
1681 foundName = dnameName;
1682 foundQT = QType::DNAME;
1683 break;
1684 }
1685 } while(!labels.empty());
1686 }
1687
1688 if (foundName.empty()) {
1689 return false;
1690 }
1691
1692 if (qtype == QType::DS && authZone == qname) {
1693 /* CNAME at APEX of the child zone, we can't use that to prove that
1694 there is no DS */
1695 LOG(prefix<<qname<<": Found a "<<foundQT.toString()<<" cache hit of '"<< qname <<"' from "<<authZone<<", but such a record at the apex of the child zone does not prove that there is no DS in the parent zone"<<endl);
1696 return false;
1697 }
1698
1699 for(auto const &record : cset) {
1700 if (record.d_class != QClass::IN) {
1701 continue;
1702 }
1703
1704 if(record.d_ttl > (unsigned int) d_now.tv_sec) {
1705
1706 if (!wasAuthZone && shouldValidate() && (wasAuth || wasForwardRecurse) && state == vState::Indeterminate && d_requireAuthData) {
1707 /* This means we couldn't figure out the state when this entry was cached */
1708
1709 vState recordState = getValidationStatus(foundName, !signatures.empty(), qtype == QType::DS, depth);
1710 if (recordState == vState::Secure) {
1711 LOG(prefix<<qname<<": got vState::Indeterminate state from the "<<foundQT.toString()<<" cache, validating.."<<endl);
1712 state = SyncRes::validateRecordsWithSigs(depth, qname, qtype, foundName, foundQT, cset, signatures);
1713 if (state != vState::Indeterminate) {
1714 LOG(prefix<<qname<<": got vState::Indeterminate state from the "<<foundQT.toString()<<" cache, new validation result is "<<state<<endl);
1715 if (vStateIsBogus(state)) {
1716 capTTL = s_maxbogusttl;
1717 }
1718 updateValidationStatusInCache(foundName, foundQT, wasAuth, state);
1719 }
1720 }
1721 }
1722
1723 LOG(prefix<<qname<<": Found cache "<<foundQT.toString()<<" hit for '"<< foundName << "|"<<foundQT.toString()<<"' to '"<<record.d_content->getZoneRepresentation()<<"', validation state is "<<state<<endl);
1724
1725 DNSRecord dr = record;
1726 dr.d_ttl -= d_now.tv_sec;
1727 dr.d_ttl = std::min(dr.d_ttl, capTTL);
1728 const uint32_t ttl = dr.d_ttl;
1729 ret.reserve(ret.size() + 2 + signatures.size() + authorityRecs.size());
1730 ret.push_back(dr);
1731
1732 for(const auto& signature : signatures) {
1733 DNSRecord sigdr;
1734 sigdr.d_type=QType::RRSIG;
1735 sigdr.d_name=foundName;
1736 sigdr.d_ttl=ttl;
1737 sigdr.d_content=signature;
1738 sigdr.d_place=DNSResourceRecord::ANSWER;
1739 sigdr.d_class=QClass::IN;
1740 ret.push_back(sigdr);
1741 }
1742
1743 for(const auto& rec : authorityRecs) {
1744 DNSRecord authDR(*rec);
1745 authDR.d_ttl=ttl;
1746 ret.push_back(authDR);
1747 }
1748
1749 DNSName newTarget;
1750 if (foundQT == QType::DNAME) {
1751 if (qtype == QType::DNAME && qname == foundName) { // client wanted the DNAME, no need to synthesize a CNAME
1752 res = RCode::NoError;
1753 return true;
1754 }
1755 // Synthesize a CNAME
1756 auto dnameRR = getRR<DNAMERecordContent>(record);
1757 if (dnameRR == nullptr) {
1758 throw ImmediateServFailException("Unable to get record content for "+foundName.toLogString()+"|DNAME cache entry");
1759 }
1760 const auto& dnameSuffix = dnameRR->getTarget();
1761 DNSName targetPrefix = qname.makeRelative(foundName);
1762 try {
1763 dr.d_type = QType::CNAME;
1764 dr.d_name = targetPrefix + foundName;
1765 newTarget = targetPrefix + dnameSuffix;
1766 dr.d_content = std::make_shared<CNAMERecordContent>(CNAMERecordContent(newTarget));
1767 ret.push_back(dr);
1768 } catch (const std::exception &e) {
1769 // We should probably catch an std::range_error here and set the rcode to YXDOMAIN (RFC 6672, section 2.2)
1770 // But this is consistent with processRecords
1771 throw ImmediateServFailException("Unable to perform DNAME substitution(DNAME owner: '" + foundName.toLogString() +
1772 "', DNAME target: '" + dnameSuffix.toLogString() + "', substituted name: '" +
1773 targetPrefix.toLogString() + "." + dnameSuffix.toLogString() +
1774 "' : " + e.what());
1775 }
1776
1777 LOG(prefix<<qname<<": Synthesized "<<dr.d_name<<"|CNAME "<<newTarget<<endl);
1778 }
1779
1780 if(qtype == QType::CNAME) { // perhaps they really wanted a CNAME!
1781 res = RCode::NoError;
1782 return true;
1783 }
1784
1785 if (qtype == QType::DS || qtype == QType::DNSKEY) {
1786 res = RCode::NoError;
1787 return true;
1788 }
1789
1790 // We have a DNAME _or_ CNAME cache hit and the client wants something else than those two.
1791 // Let's find the answer!
1792 if (foundQT == QType::CNAME) {
1793 const auto cnameContent = getRR<CNAMERecordContent>(record);
1794 if (cnameContent == nullptr) {
1795 throw ImmediateServFailException("Unable to get record content for "+foundName.toLogString()+"|CNAME cache entry");
1796 }
1797 newTarget = cnameContent->getTarget();
1798 }
1799
1800 if (qname == newTarget) {
1801 string msg = "got a CNAME referral (from cache) to self";
1802 LOG(prefix<<qname<<": "<<msg<<endl);
1803 throw ImmediateServFailException(msg);
1804 }
1805
1806 if (newTarget.isPartOf(qname)) {
1807 // a.b.c. CNAME x.a.b.c will go to great depths with QM on
1808 string msg = "got a CNAME referral (from cache) to child, disabling QM";
1809 LOG(prefix<<qname<<": "<<msg<<endl);
1810 setQNameMinimization(false);
1811 }
1812
1813 if (!d_followCNAME) {
1814 res = RCode::NoError;
1815 return true;
1816 }
1817
1818 // Check to see if we already have seen the new target as a previous target
1819 if (scanForCNAMELoop(newTarget, ret)) {
1820 string msg = "got a CNAME referral (from cache) that causes a loop";
1821 LOG(prefix<<qname<<": status="<<msg<<endl);
1822 throw ImmediateServFailException(msg);
1823 }
1824
1825 set<GetBestNSAnswer>beenthere;
1826 vState cnameState = vState::Indeterminate;
1827 // Be aware that going out on the network might be disabled (cache-only), for example because we are in QM Step0,
1828 // so you can't trust that a real lookup will have been made.
1829 res = doResolve(newTarget, qtype, ret, depth+1, beenthere, cnameState);
1830 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<state<<" with the state from the DNAME/CNAME quest: "<<cnameState<<endl);
1831 updateValidationState(state, cnameState);
1832
1833 return true;
1834 }
1835 }
1836 throw ImmediateServFailException("Could not determine whether or not there was a CNAME or DNAME in cache for '" + qname.toLogString() + "'");
1837 }
1838
1839 namespace {
1840 struct CacheEntry
1841 {
1842 vector<DNSRecord> records;
1843 vector<shared_ptr<RRSIGRecordContent>> signatures;
1844 uint32_t signaturesTTL{std::numeric_limits<uint32_t>::max()};
1845 };
1846 struct CacheKey
1847 {
1848 DNSName name;
1849 QType type;
1850 DNSResourceRecord::Place place;
1851 bool operator<(const CacheKey& rhs) const {
1852 return std::tie(type, place, name) < std::tie(rhs.type, rhs.place, rhs.name);
1853 }
1854 };
1855 typedef map<CacheKey, CacheEntry> tcache_t;
1856 }
1857
1858 static void reapRecordsFromNegCacheEntryForValidation(tcache_t& tcache, const vector<DNSRecord>& records)
1859 {
1860 for (const auto& rec : records) {
1861 if (rec.d_type == QType::RRSIG) {
1862 auto rrsig = getRR<RRSIGRecordContent>(rec);
1863 if (rrsig) {
1864 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
1865 }
1866 } else {
1867 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(rec);
1868 }
1869 }
1870 }
1871
1872 static bool negativeCacheEntryHasSOA(const NegCache::NegCacheEntry& ne)
1873 {
1874 return !ne.authoritySOA.records.empty();
1875 }
1876
1877 static void reapRecordsForValidation(std::map<QType, CacheEntry>& entries, const vector<DNSRecord>& records)
1878 {
1879 for (const auto& rec : records) {
1880 entries[rec.d_type].records.push_back(rec);
1881 }
1882 }
1883
1884 static void reapSignaturesForValidation(std::map<QType, CacheEntry>& entries, const vector<std::shared_ptr<RRSIGRecordContent>>& signatures)
1885 {
1886 for (const auto& sig : signatures) {
1887 entries[sig->d_type].signatures.push_back(sig);
1888 }
1889 }
1890
1891 /*!
1892 * Convenience function to push the records from records into ret with a new TTL
1893 *
1894 * \param records DNSRecords that need to go into ret
1895 * \param ttl The new TTL for these records
1896 * \param ret The vector of DNSRecords that should contain the records with the modified TTL
1897 */
1898 static void addTTLModifiedRecords(vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
1899 for (auto& rec : records) {
1900 rec.d_ttl = ttl;
1901 ret.push_back(std::move(rec));
1902 }
1903 }
1904
1905 void SyncRes::computeNegCacheValidationStatus(const NegCache::NegCacheEntry& ne, const DNSName& qname, const QType qtype, const int res, vState& state, unsigned int depth)
1906 {
1907 tcache_t tcache;
1908 reapRecordsFromNegCacheEntryForValidation(tcache, ne.authoritySOA.records);
1909 reapRecordsFromNegCacheEntryForValidation(tcache, ne.authoritySOA.signatures);
1910 reapRecordsFromNegCacheEntryForValidation(tcache, ne.DNSSECRecords.records);
1911 reapRecordsFromNegCacheEntryForValidation(tcache, ne.DNSSECRecords.signatures);
1912
1913 for (const auto& entry : tcache) {
1914 // this happens when we did store signatures, but passed on the records themselves
1915 if (entry.second.records.empty()) {
1916 continue;
1917 }
1918
1919 const DNSName& owner = entry.first.name;
1920
1921 vState recordState = getValidationStatus(owner, !entry.second.signatures.empty(), qtype == QType::DS, depth);
1922 if (state == vState::Indeterminate) {
1923 state = recordState;
1924 }
1925
1926 if (recordState == vState::Secure) {
1927 recordState = SyncRes::validateRecordsWithSigs(depth, qname, qtype, owner, QType(entry.first.type), entry.second.records, entry.second.signatures);
1928 }
1929
1930 if (recordState != vState::Indeterminate && recordState != state) {
1931 updateValidationState(state, recordState);
1932 if (state != vState::Secure) {
1933 break;
1934 }
1935 }
1936 }
1937
1938 if (state == vState::Secure) {
1939 vState neValidationState = ne.d_validationState;
1940 dState expectedState = res == RCode::NXDomain ? dState::NXDOMAIN : dState::NXQTYPE;
1941 dState denialState = getDenialValidationState(ne, expectedState, false);
1942 updateDenialValidationState(neValidationState, ne.d_name, state, denialState, expectedState, qtype == QType::DS, depth);
1943 }
1944 if (state != vState::Indeterminate) {
1945 /* validation succeeded, let's update the cache entry so we don't have to validate again */
1946 boost::optional<time_t> capTTD = boost::none;
1947 if (vStateIsBogus(state)) {
1948 capTTD = d_now.tv_sec + s_maxbogusttl;
1949 }
1950 g_negCache->updateValidationStatus(ne.d_name, ne.d_qtype, state, capTTD);
1951 }
1952 }
1953
1954 bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, QType qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
1955 {
1956 bool giveNegative=false;
1957
1958 string prefix;
1959 if(doLog()) {
1960 prefix=d_prefix;
1961 prefix.append(depth, ' ');
1962 }
1963
1964 // sqname and sqtype are used contain 'higher' names if we have them (e.g. powerdns.com|SOA when we find a negative entry for doesnotexist.powerdns.com|A)
1965 DNSName sqname(qname);
1966 QType sqt(qtype);
1967 uint32_t sttl=0;
1968 // cout<<"Lookup for '"<<qname<<"|"<<qtype.toString()<<"' -> "<<getLastLabel(qname)<<endl;
1969 vState cachedState;
1970 NegCache::NegCacheEntry ne;
1971
1972 if(s_rootNXTrust &&
1973 g_negCache->getRootNXTrust(qname, d_now, ne) &&
1974 ne.d_auth.isRoot() &&
1975 !(wasForwardedOrAuthZone && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
1976 sttl = ne.d_ttd - d_now.tv_sec;
1977 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' & '"<<ne.d_name<<"' for another "<<sttl<<" seconds"<<endl);
1978 res = RCode::NXDomain;
1979 giveNegative = true;
1980 cachedState = ne.d_validationState;
1981 } else if (g_negCache->get(qname, qtype, d_now, ne)) {
1982 /* If we are looking for a DS, discard NXD if auth == qname
1983 and ask for a specific denial instead */
1984 if (qtype != QType::DS || ne.d_qtype.getCode() || ne.d_auth != qname ||
1985 g_negCache->get(qname, qtype, d_now, ne, true))
1986 {
1987 /* Careful! If the client is asking for a DS that does not exist, we need to provide the SOA along with the NSEC(3) proof
1988 and we might not have it if we picked up the proof from a delegation, in which case we need to keep on to do the actual DS
1989 query. */
1990 if (qtype == QType::DS && ne.d_qtype.getCode() && !d_externalDSQuery.empty() && qname == d_externalDSQuery && !negativeCacheEntryHasSOA(ne)) {
1991 giveNegative = false;
1992 }
1993 else {
1994 res = RCode::NXDomain;
1995 sttl = ne.d_ttd - d_now.tv_sec;
1996 giveNegative = true;
1997 cachedState = ne.d_validationState;
1998 if (ne.d_qtype.getCode()) {
1999 LOG(prefix<<qname<<": "<<qtype<<" is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
2000 res = RCode::NoError;
2001 } else {
2002 LOG(prefix<<qname<<": Entire name '"<<qname<<"' is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
2003 }
2004 }
2005 }
2006 } else if (s_hardenNXD != HardenNXD::No && !qname.isRoot() && !wasForwardedOrAuthZone) {
2007 auto labels = qname.getRawLabels();
2008 DNSName negCacheName(g_rootdnsname);
2009 negCacheName.prependRawLabel(labels.back());
2010 labels.pop_back();
2011 while(!labels.empty()) {
2012 if (g_negCache->get(negCacheName, QType::ENT, d_now, ne, true)) {
2013 if (ne.d_validationState == vState::Indeterminate && validationEnabled()) {
2014 // LOG(prefix << negCacheName << " negatively cached and vState::Indeterminate, trying to validate NXDOMAIN" << endl);
2015 // ...
2016 // And get the updated ne struct
2017 //t_sstorage.negcache.get(negCacheName, QType(0), d_now, ne, true);
2018 }
2019 if ((s_hardenNXD == HardenNXD::Yes && !vStateIsBogus(ne.d_validationState)) || ne.d_validationState == vState::Secure) {
2020 res = RCode::NXDomain;
2021 sttl = ne.d_ttd - d_now.tv_sec;
2022 giveNegative = true;
2023 cachedState = ne.d_validationState;
2024 LOG(prefix<<qname<<": Name '"<<negCacheName<<"' and below, is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
2025 break;
2026 }
2027 }
2028 negCacheName.prependRawLabel(labels.back());
2029 labels.pop_back();
2030 }
2031 }
2032
2033 if (giveNegative) {
2034
2035 state = cachedState;
2036
2037 if (!wasAuthZone && shouldValidate() && state == vState::Indeterminate) {
2038 LOG(prefix<<qname<<": got vState::Indeterminate state for records retrieved from the negative cache, validating.."<<endl);
2039 computeNegCacheValidationStatus(ne, qname, qtype, res, state, depth);
2040
2041 if (state != cachedState && vStateIsBogus(state)) {
2042 sttl = std::min(sttl, s_maxbogusttl);
2043 }
2044 }
2045
2046 // Transplant SOA to the returned packet
2047 addTTLModifiedRecords(ne.authoritySOA.records, sttl, ret);
2048 if(d_doDNSSEC) {
2049 addTTLModifiedRecords(ne.authoritySOA.signatures, sttl, ret);
2050 addTTLModifiedRecords(ne.DNSSECRecords.records, sttl, ret);
2051 addTTLModifiedRecords(ne.DNSSECRecords.signatures, sttl, ret);
2052 }
2053
2054 LOG(prefix<<qname<<": updating validation state with negative cache content for "<<qname<<" to "<<state<<endl);
2055 return true;
2056 }
2057
2058 vector<DNSRecord> cset;
2059 bool found=false, expired=false;
2060 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
2061 vector<std::shared_ptr<DNSRecord>> authorityRecs;
2062 uint32_t ttl=0;
2063 uint32_t capTTL = std::numeric_limits<uint32_t>::max();
2064 bool wasCachedAuth;
2065
2066 if(g_recCache->get(d_now.tv_sec, sqname, sqt, !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_refresh, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth, nullptr, &d_fromAuthIP) > 0) {
2067
2068 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.toString()<<": ");
2069
2070 if (!wasAuthZone && shouldValidate() && (wasCachedAuth || wasForwardRecurse) && cachedState == vState::Indeterminate && d_requireAuthData) {
2071
2072 /* This means we couldn't figure out the state when this entry was cached */
2073 vState recordState = getValidationStatus(qname, !signatures.empty(), qtype == QType::DS, depth);
2074
2075 if (recordState == vState::Secure) {
2076 LOG(prefix<<sqname<<": got vState::Indeterminate state from the cache, validating.."<<endl);
2077 if (sqt == QType::DNSKEY && sqname == getSigner(signatures)) {
2078 cachedState = validateDNSKeys(sqname, cset, signatures, depth);
2079 }
2080 else {
2081 if (sqt == QType::ANY) {
2082 std::map<QType, CacheEntry> types;
2083 reapRecordsForValidation(types, cset);
2084 reapSignaturesForValidation(types, signatures);
2085
2086 for (const auto& type : types) {
2087 vState cachedRecordState;
2088 if (type.first == QType::DNSKEY && sqname == getSigner(type.second.signatures)) {
2089 cachedRecordState = validateDNSKeys(sqname, type.second.records, type.second.signatures, depth);
2090 }
2091 else {
2092 cachedRecordState = SyncRes::validateRecordsWithSigs(depth, qname, qtype, sqname, type.first, type.second.records, type.second.signatures);
2093 }
2094 updateDNSSECValidationState(cachedState, cachedRecordState);
2095 }
2096 }
2097 else {
2098 cachedState = SyncRes::validateRecordsWithSigs(depth, qname, qtype, sqname, sqt, cset, signatures);
2099 }
2100 }
2101 }
2102 else {
2103 cachedState = recordState;
2104 }
2105
2106 if (cachedState != vState::Indeterminate) {
2107 LOG(prefix<<qname<<": got vState::Indeterminate state from the cache, validation result is "<<cachedState<<endl);
2108 if (vStateIsBogus(cachedState)) {
2109 capTTL = s_maxbogusttl;
2110 }
2111 if (sqt != QType::ANY && sqt != QType::ADDR) {
2112 updateValidationStatusInCache(sqname, sqt, wasCachedAuth, cachedState);
2113 }
2114 }
2115 }
2116
2117 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
2118
2119 LOG(j->d_content->getZoneRepresentation());
2120
2121 if (j->d_class != QClass::IN) {
2122 continue;
2123 }
2124
2125 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
2126 DNSRecord dr=*j;
2127 dr.d_ttl -= d_now.tv_sec;
2128 dr.d_ttl = std::min(dr.d_ttl, capTTL);
2129 ttl = dr.d_ttl;
2130 ret.push_back(dr);
2131 LOG("[ttl="<<dr.d_ttl<<"] ");
2132 found=true;
2133 }
2134 else {
2135 LOG("[expired] ");
2136 expired=true;
2137 }
2138 }
2139
2140 ret.reserve(ret.size() + signatures.size() + authorityRecs.size());
2141
2142 for(const auto& signature : signatures) {
2143 DNSRecord dr;
2144 dr.d_type=QType::RRSIG;
2145 dr.d_name=sqname;
2146 dr.d_ttl=ttl;
2147 dr.d_content=signature;
2148 dr.d_place = DNSResourceRecord::ANSWER;
2149 dr.d_class=QClass::IN;
2150 ret.push_back(dr);
2151 }
2152
2153 for(const auto& rec : authorityRecs) {
2154 DNSRecord dr(*rec);
2155 dr.d_ttl=ttl;
2156 ret.push_back(dr);
2157 }
2158
2159 LOG(endl);
2160 if(found && !expired) {
2161 if (!giveNegative)
2162 res=0;
2163 LOG(prefix<<qname<<": updating validation state with cache content for "<<qname<<" to "<<cachedState<<endl);
2164 state = cachedState;
2165 return true;
2166 }
2167 else
2168 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
2169 }
2170
2171 /* let's check if we have a NSEC covering that record */
2172 if (g_aggressiveNSECCache && !wasForwardedOrAuthZone) {
2173 if (g_aggressiveNSECCache->getDenial(d_now.tv_sec, qname, qtype, ret, res, d_cacheRemote, d_routingTag, d_doDNSSEC)) {
2174 state = vState::Secure;
2175 return true;
2176 }
2177 }
2178
2179 return false;
2180 }
2181
2182 bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
2183 {
2184 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
2185 }
2186
2187 struct speedOrder
2188 {
2189 bool operator()(const std::pair<DNSName, float> &a, const std::pair<DNSName, float> &b) const
2190 {
2191 return a.second < b.second;
2192 }
2193 };
2194
2195 inline std::vector<std::pair<DNSName, float>> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
2196 {
2197 std::vector<std::pair<DNSName, float>> rnameservers;
2198 rnameservers.reserve(tnameservers.size());
2199 for(const auto& tns: tnameservers) {
2200 float speed = t_sstorage.nsSpeeds[tns.first].get(d_now);
2201 rnameservers.emplace_back(tns.first, speed);
2202 if(tns.first.empty()) // this was an authoritative OOB zone, don't pollute the nsSpeeds with that
2203 return rnameservers;
2204 }
2205
2206 shuffle(rnameservers.begin(),rnameservers.end(), pdns::dns_random_engine());
2207 speedOrder so;
2208 stable_sort(rnameservers.begin(),rnameservers.end(), so);
2209
2210 if(doLog()) {
2211 LOG(prefix<<"Nameservers: ");
2212 for(auto i=rnameservers.begin();i!=rnameservers.end();++i) {
2213 if(i!=rnameservers.begin()) {
2214 LOG(", ");
2215 if(!((i-rnameservers.begin())%3)) {
2216 LOG(endl<<prefix<<" ");
2217 }
2218 }
2219 LOG(i->first.toLogString()<<"(" << fmtfloat("%0.2f", i->second/1000.0) <<"ms)");
2220 }
2221 LOG(endl);
2222 }
2223 return rnameservers;
2224 }
2225
2226 inline vector<ComboAddress> SyncRes::shuffleForwardSpeed(const vector<ComboAddress> &rnameservers, const string &prefix, const bool wasRd)
2227 {
2228 vector<ComboAddress> nameservers = rnameservers;
2229 map<ComboAddress, float> speeds;
2230
2231 for(const auto& val: nameservers) {
2232 float speed;
2233 DNSName nsName = DNSName(val.toStringWithPort());
2234 speed=t_sstorage.nsSpeeds[nsName].get(d_now);
2235 speeds[val]=speed;
2236 }
2237 shuffle(nameservers.begin(),nameservers.end(), pdns::dns_random_engine());
2238 speedOrderCA so(speeds);
2239 stable_sort(nameservers.begin(),nameservers.end(), so);
2240
2241 if(doLog()) {
2242 LOG(prefix<<"Nameservers: ");
2243 for(vector<ComboAddress>::const_iterator i=nameservers.cbegin();i!=nameservers.cend();++i) {
2244 if(i!=nameservers.cbegin()) {
2245 LOG(", ");
2246 if(!((i-nameservers.cbegin())%3)) {
2247 LOG(endl<<prefix<<" ");
2248 }
2249 }
2250 LOG((wasRd ? string("+") : string("-")) << i->toStringWithPort() <<"(" << fmtfloat("%0.2f", speeds[*i]/1000.0) <<"ms)");
2251 }
2252 LOG(endl);
2253 }
2254 return nameservers;
2255 }
2256
2257 static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<RRSIGRecordContent>& rrsig)
2258 {
2259 uint32_t res = 0;
2260 if (now < rrsig->d_sigexpire) {
2261 res = static_cast<uint32_t>(rrsig->d_sigexpire) - now;
2262 }
2263 return res;
2264 }
2265
2266 static const set<QType> nsecTypes = {QType::NSEC, QType::NSEC3};
2267
2268 /* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
2269 *
2270 * \param records The records to parse for the authority SOA and NSEC(3) records
2271 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
2272 */
2273 static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne, const time_t now, uint32_t* lowestTTL) {
2274 for (const auto& rec : records) {
2275 if (rec.d_place != DNSResourceRecord::AUTHORITY) {
2276 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
2277 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
2278 // records MUST be in the same section as the records they cover.
2279 // Hence, we ignore all records outside of the AUTHORITY section.
2280 continue;
2281 }
2282
2283 if (rec.d_type == QType::RRSIG) {
2284 auto rrsig = getRR<RRSIGRecordContent>(rec);
2285 if (rrsig) {
2286 if (rrsig->d_type == QType::SOA) {
2287 ne.authoritySOA.signatures.push_back(rec);
2288 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
2289 *lowestTTL = min(*lowestTTL, rec.d_ttl);
2290 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
2291 }
2292 }
2293 if (nsecTypes.count(rrsig->d_type)) {
2294 ne.DNSSECRecords.signatures.push_back(rec);
2295 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
2296 *lowestTTL = min(*lowestTTL, rec.d_ttl);
2297 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
2298 }
2299 }
2300 }
2301 continue;
2302 }
2303 if (rec.d_type == QType::SOA) {
2304 ne.authoritySOA.records.push_back(rec);
2305 if (lowestTTL) {
2306 *lowestTTL = min(*lowestTTL, rec.d_ttl);
2307 }
2308 continue;
2309 }
2310 if (nsecTypes.count(rec.d_type)) {
2311 ne.DNSSECRecords.records.push_back(rec);
2312 if (lowestTTL) {
2313 *lowestTTL = min(*lowestTTL, rec.d_ttl);
2314 }
2315 continue;
2316 }
2317 }
2318 }
2319
2320 static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
2321 {
2322 cspmap_t cspmap;
2323 for(const auto& rec : ne.DNSSECRecords.signatures) {
2324 if(rec.d_type == QType::RRSIG) {
2325 auto rrc = getRR<RRSIGRecordContent>(rec);
2326 if (rrc) {
2327 cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
2328 }
2329 }
2330 }
2331 for(const auto& rec : ne.DNSSECRecords.records) {
2332 cspmap[{rec.d_name, rec.d_type}].records.insert(rec.d_content);
2333 }
2334 return cspmap;
2335 }
2336
2337 // TODO remove after processRecords is fixed!
2338 // Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
2339 static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
2340 {
2341 NegCache::NegCacheEntry ne;
2342 harvestNXRecords(records, ne, 0, nullptr);
2343 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
2344 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
2345 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
2346 }
2347
2348 static bool rpzHitShouldReplaceContent(const DNSName& qname, const QType qtype, const std::vector<DNSRecord>& records)
2349 {
2350 if (qtype == QType::CNAME) {
2351 return true;
2352 }
2353
2354 for (const auto& record : records) {
2355 if (record.d_type == QType::CNAME) {
2356 if (auto content = getRR<CNAMERecordContent>(record)) {
2357 if (qname == content->getTarget()) {
2358 /* we have a CNAME whose target matches the entry we are about to
2359 generate, so it will complete the current records, not replace
2360 them
2361 */
2362 return false;
2363 }
2364 }
2365 }
2366 }
2367
2368 return true;
2369 }
2370
2371 static void removeConflictingRecord(std::vector<DNSRecord>& records, const DNSName& name, const QType dtype)
2372 {
2373 for (auto it = records.begin(); it != records.end(); ) {
2374 bool remove = false;
2375
2376 if (it->d_class == QClass::IN &&
2377 (it->d_type == QType::CNAME || dtype == QType::CNAME || it->d_type == dtype) &&
2378 it->d_name == name) {
2379 remove = true;
2380 }
2381 else if (it->d_class == QClass::IN &&
2382 it->d_type == QType::RRSIG &&
2383 it->d_name == name) {
2384 if (auto rrc = getRR<RRSIGRecordContent>(*it)) {
2385 if (rrc->d_type == QType::CNAME || rrc->d_type == dtype) {
2386 /* also remove any RRSIG that could conflict */
2387 remove = true;
2388 }
2389 }
2390 }
2391
2392 if (remove) {
2393 it = records.erase(it);
2394 }
2395 else {
2396 ++it;
2397 }
2398 }
2399 }
2400
2401 void SyncRes::handlePolicyHit(const std::string& prefix, const DNSName& qname, const QType qtype, std::vector<DNSRecord>& ret, bool& done, int& rcode, unsigned int depth)
2402 {
2403 if (d_pdl && d_pdl->policyHitEventFilter(d_requestor, qname, qtype, d_queryReceivedOverTCP, d_appliedPolicy, d_policyTags, d_discardedPolicies)) {
2404 /* reset to no match */
2405 d_appliedPolicy = DNSFilterEngine::Policy();
2406 return;
2407 }
2408
2409 /* don't account truncate actions for TCP queries, since they are not applied */
2410 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::Truncate || !d_queryReceivedOverTCP) {
2411 ++g_stats.policyResults[d_appliedPolicy.d_kind];
2412 ++(g_stats.policyHits.lock()->operator[](d_appliedPolicy.getName()));
2413 }
2414
2415 if (d_appliedPolicy.d_type != DNSFilterEngine::PolicyType::None) {
2416 LOG(prefix << qname << "|" << qtype << d_appliedPolicy.getLogString() << endl);
2417 }
2418
2419 switch (d_appliedPolicy.d_kind) {
2420
2421 case DNSFilterEngine::PolicyKind::NoAction:
2422 return;
2423
2424 case DNSFilterEngine::PolicyKind::Drop:
2425 ++g_stats.policyDrops;
2426 throw ImmediateQueryDropException();
2427
2428 case DNSFilterEngine::PolicyKind::NXDOMAIN:
2429 ret.clear();
2430 rcode = RCode::NXDomain;
2431 done = true;
2432 return;
2433
2434 case DNSFilterEngine::PolicyKind::NODATA:
2435 ret.clear();
2436 rcode = RCode::NoError;
2437 done = true;
2438 return;
2439
2440 case DNSFilterEngine::PolicyKind::Truncate:
2441 if (!d_queryReceivedOverTCP) {
2442 ret.clear();
2443 rcode = RCode::NoError;
2444 throw SendTruncatedAnswerException();
2445 }
2446 return;
2447
2448 case DNSFilterEngine::PolicyKind::Custom:
2449 {
2450 if (rpzHitShouldReplaceContent(qname, qtype, ret)) {
2451 ret.clear();
2452 }
2453
2454 rcode = RCode::NoError;
2455 done = true;
2456 auto spoofed = d_appliedPolicy.getCustomRecords(qname, qtype.getCode());
2457 for (auto& dr : spoofed) {
2458 removeConflictingRecord(ret, dr.d_name, dr.d_type);
2459 }
2460
2461 for (auto& dr : spoofed) {
2462 ret.push_back(dr);
2463
2464 if (dr.d_name == qname && dr.d_type == QType::CNAME && qtype != QType::CNAME) {
2465 if (auto content = getRR<CNAMERecordContent>(dr)) {
2466 vState newTargetState = vState::Indeterminate;
2467 handleNewTarget(prefix, qname, content->getTarget(), qtype.getCode(), ret, rcode, depth, {}, newTargetState);
2468 }
2469 }
2470 }
2471 }
2472 }
2473 }
2474
2475 bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
2476 {
2477 /* we skip RPZ processing if:
2478 - it was disabled (d_wantsRPZ is false) ;
2479 - we already got a RPZ hit (d_appliedPolicy.d_type != DNSFilterEngine::PolicyType::None) since
2480 the only way we can get back here is that it was a 'pass-thru' (NoAction) meaning that we should not
2481 process any further RPZ rules. Except that we need to process rules of higher priority..
2482 */
2483 if (d_wantsRPZ && !d_appliedPolicy.wasHit()) {
2484 for (auto const &ns : nameservers) {
2485 bool match = dfe.getProcessingPolicy(ns.first, d_discardedPolicies, d_appliedPolicy);
2486 if (match) {
2487 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
2488 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2489 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<d_appliedPolicy.getName()<<"'"<<endl);
2490 return true;
2491 }
2492 }
2493
2494 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
2495 for (auto const &address : ns.second.first) {
2496 match = dfe.getProcessingPolicy(address, d_discardedPolicies, d_appliedPolicy);
2497 if (match) {
2498 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
2499 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2500 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<d_appliedPolicy.getName()<<"'"<<endl);
2501 return true;
2502 }
2503 }
2504 }
2505 }
2506 }
2507 return false;
2508 }
2509
2510 bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
2511 {
2512 /* we skip RPZ processing if:
2513 - it was disabled (d_wantsRPZ is false) ;
2514 - we already got a RPZ hit (d_appliedPolicy.d_type != DNSFilterEngine::PolicyType::None) since
2515 the only way we can get back here is that it was a 'pass-thru' (NoAction) meaning that we should not
2516 process any further RPZ rules. Except that we need to process rules of higher priority..
2517 */
2518 if (d_wantsRPZ && !d_appliedPolicy.wasHit()) {
2519 bool match = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies, d_appliedPolicy);
2520 if (match) {
2521 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
2522 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
2523 LOG(" (blocked by RPZ policy '" + d_appliedPolicy.getName() + "')");
2524 return true;
2525 }
2526 }
2527 }
2528 return false;
2529 }
2530
2531 vector<ComboAddress> SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, std::vector<std::pair<DNSName, float>>::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<std::pair<DNSName, float>>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly, unsigned int &nretrieveAddressesForNS)
2532 {
2533 vector<ComboAddress> result;
2534
2535 size_t nonresolvingfails = 0;
2536 if (!tns->first.empty()) {
2537 if (s_nonresolvingnsmaxfails > 0) {
2538 nonresolvingfails = s_nonresolving.lock()->value(tns->first);
2539 if (nonresolvingfails >= s_nonresolvingnsmaxfails) {
2540 LOG(prefix<<qname<<": NS "<<tns->first<< " in non-resolving map, skipping"<<endl);
2541 return result;
2542 }
2543 }
2544
2545 LOG(prefix<<qname<<": Trying to resolve NS '"<<tns->first<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
2546 const unsigned int oldOutQueries = d_outqueries;
2547 try {
2548 result = getAddrs(tns->first, depth, beenthere, cacheOnly, nretrieveAddressesForNS);
2549 }
2550 // Other exceptions should likely not throttle...
2551 catch (const ImmediateServFailException& ex) {
2552 if (s_nonresolvingnsmaxfails > 0 && d_outqueries > oldOutQueries) {
2553 auto dontThrottleNames = g_dontThrottleNames.getLocal();
2554 if (!dontThrottleNames->check(tns->first)) {
2555 s_nonresolving.lock()->incr(tns->first, d_now);
2556 }
2557 }
2558 throw ex;
2559 }
2560 if (s_nonresolvingnsmaxfails > 0 && d_outqueries > oldOutQueries) {
2561 if (result.empty()) {
2562 auto dontThrottleNames = g_dontThrottleNames.getLocal();
2563 if (!dontThrottleNames->check(tns->first)) {
2564 s_nonresolving.lock()->incr(tns->first, d_now);
2565 }
2566 }
2567 else if (nonresolvingfails > 0) {
2568 // Succeeding resolve, clear memory of recent failures
2569 s_nonresolving.lock()->clear(tns->first);
2570 }
2571 }
2572 pierceDontQuery=false;
2573 }
2574 else {
2575 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
2576
2577 if(nameservers[tns->first].first.size() > 1) {
2578 LOG("s");
2579 }
2580 LOG(endl);
2581
2582 sendRDQuery = nameservers[tns->first].second;
2583 result = shuffleForwardSpeed(nameservers[tns->first].first, doLog() ? (prefix+qname.toString()+": ") : string(), sendRDQuery);
2584 pierceDontQuery=true;
2585 }
2586 return result;
2587 }
2588
2589 bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType qtype, bool pierceDontQuery)
2590 {
2591 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, std::make_tuple(remoteIP, g_rootdnsname, 0))) {
2592 LOG(prefix<<qname<<": server throttled "<<endl);
2593 s_throttledqueries++; d_throttledqueries++;
2594 return true;
2595 }
2596 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, std::make_tuple(remoteIP, qname, qtype.getCode()))) {
2597 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype<<endl);
2598 s_throttledqueries++; d_throttledqueries++;
2599 return true;
2600 }
2601 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
2602 // We could have retrieved an NS from the cache in a forwarding domain
2603 // Even in the case of !pierceDontQuery we still want to allow that NS
2604 DNSName forwardCandidate(qname);
2605 auto it = getBestAuthZone(&forwardCandidate);
2606 if (it == t_sstorage.domainmap->end()) {
2607 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
2608 s_dontqueries++;
2609 return true;
2610 } else {
2611 // The name (from the cache) is forwarded, but is it forwarded to an IP in known forwarders?
2612 const auto& ips = it->second.d_servers;
2613 if (std::find(ips.cbegin(), ips.cend(), remoteIP) == ips.cend()) {
2614 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
2615 s_dontqueries++;
2616 return true;
2617 } else {
2618 LOG(prefix<<qname<<": sending query to " << remoteIP.toString() << ", blocked by 'dont-query' but a forwarding/auth case" << endl);
2619 }
2620 }
2621 }
2622 return false;
2623 }
2624
2625 bool SyncRes::validationEnabled() const
2626 {
2627 return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
2628 }
2629
2630 uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const
2631 {
2632 uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
2633 for (const auto& record : records) {
2634 lowestTTD = min(lowestTTD, record.d_ttl);
2635 }
2636
2637 /* even if it was not requested for that request (Process, and neither AD nor DO set),
2638 it might be requested at a later time so we need to be careful with the TTL. */
2639 if (validationEnabled() && !signatures.empty()) {
2640 /* if we are validating, we don't want to cache records after their signatures expire. */
2641 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
2642 lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
2643
2644 for(const auto& sig : signatures) {
2645 if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
2646 // we don't decrement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
2647 lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
2648 }
2649 }
2650 }
2651
2652 for (const auto& entry : authorityRecs) {
2653 /* be careful, this is still a TTL here */
2654 lowestTTD = min(lowestTTD, static_cast<uint32_t>(entry->d_ttl + d_now.tv_sec));
2655
2656 if (entry->d_type == QType::RRSIG && validationEnabled()) {
2657 auto rrsig = getRR<RRSIGRecordContent>(*entry);
2658 if (rrsig) {
2659 if (isRRSIGNotExpired(d_now.tv_sec, rrsig)) {
2660 // we don't decrement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
2661 lowestTTD = min(lowestTTD, static_cast<uint32_t>(rrsig->d_sigexpire));
2662 }
2663 }
2664 }
2665 }
2666
2667 return lowestTTD;
2668 }
2669
2670 void SyncRes::updateValidationState(vState& state, const vState stateUpdate)
2671 {
2672 LOG(d_prefix<<"validation state was "<<state<<", state update is "<<stateUpdate);
2673 updateDNSSECValidationState(state, stateUpdate);
2674 LOG(", validation state is now "<<state<<endl);
2675 }
2676
2677 vState SyncRes::getTA(const DNSName& zone, dsmap_t& ds)
2678 {
2679 auto luaLocal = g_luaconfs.getLocal();
2680
2681 if (luaLocal->dsAnchors.empty()) {
2682 LOG(d_prefix<<": No trust anchors configured, everything is Insecure"<<endl);
2683 /* We have no TA, everything is insecure */
2684 return vState::Insecure;
2685 }
2686
2687 std::string reason;
2688 if (haveNegativeTrustAnchor(luaLocal->negAnchors, zone, reason)) {
2689 LOG(d_prefix<<": got NTA for '"<<zone<<"'"<<endl);
2690 return vState::NTA;
2691 }
2692
2693 if (getTrustAnchor(luaLocal->dsAnchors, zone, ds)) {
2694 LOG(d_prefix<<": got TA for '"<<zone<<"'"<<endl);
2695 return vState::TA;
2696 }
2697 else {
2698 LOG(d_prefix<<": no TA found for '"<<zone<<"' among "<< luaLocal->dsAnchors.size()<<endl);
2699 }
2700
2701 if (zone.isRoot()) {
2702 /* No TA for the root */
2703 return vState::Insecure;
2704 }
2705
2706 return vState::Indeterminate;
2707 }
2708
2709 static size_t countSupportedDS(const dsmap_t& dsmap)
2710 {
2711 size_t count = 0;
2712
2713 for (const auto& ds : dsmap) {
2714 if (isSupportedDS(ds)) {
2715 count++;
2716 }
2717 }
2718
2719 return count;
2720 }
2721
2722 void SyncRes::initZoneCutsFromTA(const DNSName& from)
2723 {
2724 DNSName zone(from);
2725 do {
2726 dsmap_t ds;
2727 vState result = getTA(zone, ds);
2728 if (result != vState::Indeterminate) {
2729 if (result == vState::TA) {
2730 if (countSupportedDS(ds) == 0) {
2731 ds.clear();
2732 result = vState::Insecure;
2733 }
2734 else {
2735 result = vState::Secure;
2736 }
2737 }
2738 else if (result == vState::NTA) {
2739 result = vState::Insecure;
2740 }
2741
2742 d_cutStates[zone] = result;
2743 }
2744 }
2745 while (zone.chopOff());
2746 }
2747
2748 vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsigned int depth, bool bogusOnNXD, bool* foundCut)
2749 {
2750 vState result = getTA(zone, ds);
2751
2752 if (result != vState::Indeterminate || taOnly) {
2753 if (foundCut) {
2754 *foundCut = (result != vState::Indeterminate);
2755 }
2756
2757 if (result == vState::TA) {
2758 if (countSupportedDS(ds) == 0) {
2759 ds.clear();
2760 result = vState::Insecure;
2761 }
2762 else {
2763 result = vState::Secure;
2764 }
2765 }
2766 else if (result == vState::NTA) {
2767 result = vState::Insecure;
2768 }
2769
2770 return result;
2771 }
2772
2773 std::set<GetBestNSAnswer> beenthere;
2774 std::vector<DNSRecord> dsrecords;
2775
2776 vState state = vState::Indeterminate;
2777 const bool oldCacheOnly = setCacheOnly(false);
2778 int rcode = doResolve(zone, QType::DS, dsrecords, depth + 1, beenthere, state);
2779 setCacheOnly(oldCacheOnly);
2780
2781 if (rcode == RCode::ServFail) {
2782 throw ImmediateServFailException("Server Failure while retrieving DS records for " + zone.toLogString());
2783 }
2784
2785 if (rcode == RCode::NoError || (rcode == RCode::NXDomain && !bogusOnNXD)) {
2786 uint8_t bestDigestType = 0;
2787
2788 bool gotCNAME = false;
2789 for (const auto& record : dsrecords) {
2790 if (record.d_type == QType::DS) {
2791 const auto dscontent = getRR<DSRecordContent>(record);
2792 if (dscontent && isSupportedDS(*dscontent)) {
2793 // Make GOST a lower prio than SHA256
2794 if (dscontent->d_digesttype == DNSSECKeeper::DIGEST_GOST && bestDigestType == DNSSECKeeper::DIGEST_SHA256) {
2795 continue;
2796 }
2797 if (dscontent->d_digesttype > bestDigestType || (bestDigestType == DNSSECKeeper::DIGEST_GOST && dscontent->d_digesttype == DNSSECKeeper::DIGEST_SHA256)) {
2798 bestDigestType = dscontent->d_digesttype;
2799 }
2800 ds.insert(*dscontent);
2801 }
2802 }
2803 else if (record.d_type == QType::CNAME && record.d_name == zone) {
2804 gotCNAME = true;
2805 }
2806 }
2807
2808 /* RFC 4509 section 3: "Validator implementations SHOULD ignore DS RRs containing SHA-1
2809 * digests if DS RRs with SHA-256 digests are present in the DS RRset."
2810 * We interpret that as: do not use SHA-1 if SHA-256 or SHA-384 is available
2811 */
2812 for (auto dsrec = ds.begin(); dsrec != ds.end(); ) {
2813 if (dsrec->d_digesttype == DNSSECKeeper::DIGEST_SHA1 && dsrec->d_digesttype != bestDigestType) {
2814 dsrec = ds.erase(dsrec);
2815 }
2816 else {
2817 ++dsrec;
2818 }
2819 }
2820
2821 if (rcode == RCode::NoError) {
2822 if (ds.empty()) {
2823 /* we have no DS, it's either:
2824 - a delegation to a non-DNSSEC signed zone
2825 - no delegation, we stay in the same zone
2826 */
2827 if (gotCNAME || denialProvesNoDelegation(zone, dsrecords)) {
2828 /* we are still inside the same zone */
2829
2830 if (foundCut) {
2831 *foundCut = false;
2832 }
2833 return state;
2834 }
2835
2836 d_cutStates[zone] = state == vState::Secure ? vState::Insecure : state;
2837 /* delegation with no DS, might be Secure -> Insecure */
2838 if (foundCut) {
2839 *foundCut = true;
2840 }
2841
2842 /* a delegation with no DS is either:
2843 - a signed zone (Secure) to an unsigned one (Insecure)
2844 - an unsigned zone to another unsigned one (Insecure stays Insecure, Bogus stays Bogus)
2845 */
2846 return state == vState::Secure ? vState::Insecure : state;
2847 } else {
2848 /* we have a DS */
2849 d_cutStates[zone] = state;
2850 if (foundCut) {
2851 *foundCut = true;
2852 }
2853 }
2854 }
2855
2856 return state;
2857 }
2858
2859 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
2860 return vState::BogusUnableToGetDSs;
2861 }
2862
2863 vState SyncRes::getValidationStatus(const DNSName& name, bool wouldBeValid, bool typeIsDS, unsigned int depth)
2864 {
2865 vState result = vState::Indeterminate;
2866
2867 if (!shouldValidate()) {
2868 return result;
2869 }
2870
2871 DNSName subdomain(name);
2872 if (typeIsDS) {
2873 subdomain.chopOff();
2874 }
2875
2876 {
2877 const auto& it = d_cutStates.find(subdomain);
2878 if (it != d_cutStates.cend()) {
2879 LOG(d_prefix<<": got status "<<it->second<<" for name "<<subdomain<<endl);
2880 return it->second;
2881 }
2882 }
2883
2884 /* look for the best match we have */
2885 DNSName best(subdomain);
2886 while (best.chopOff()) {
2887 const auto& it = d_cutStates.find(best);
2888 if (it != d_cutStates.cend()) {
2889 result = it->second;
2890 if (vStateIsBogus(result) || result == vState::Insecure) {
2891 LOG(d_prefix<<": got status "<<result<<" for name "<<best<<endl);
2892 return result;
2893 }
2894 break;
2895 }
2896 }
2897
2898 /* by now we have the best match, it's likely Secure (otherwise we would not be there)
2899 but we don't know if we missed a cut (or several).
2900 We could see if we have DS (or denial of) in cache but let's not worry for now,
2901 we will if we don't have a signature, or if the signer doesn't match what we expect */
2902 if (!wouldBeValid && best != subdomain) {
2903 /* no signatures or Bogus, we likely missed a cut, let's try to find it */
2904 LOG(d_prefix<<": no or invalid signature/proof for "<<name<<", we likely missed a cut between "<<best<<" and "<<subdomain<<", looking for it"<<endl);
2905 DNSName ds(best);
2906 std::vector<string> labelsToAdd = subdomain.makeRelative(ds).getRawLabels();
2907
2908 while (!labelsToAdd.empty()) {
2909
2910 ds.prependRawLabel(labelsToAdd.back());
2911 labelsToAdd.pop_back();
2912 LOG(d_prefix<<": - Looking for a DS at "<<ds<<endl);
2913
2914 bool foundCut = false;
2915 dsmap_t results;
2916 vState dsState = getDSRecords(ds, results, false, depth, false, &foundCut);
2917
2918 if (foundCut) {
2919 LOG(d_prefix<<": - Found cut at "<<ds<<endl);
2920 LOG(d_prefix<<": New state for "<<ds<<" is "<<dsState<<endl);
2921 d_cutStates[ds] = dsState;
2922
2923 if (dsState != vState::Secure) {
2924 return dsState;
2925 }
2926 }
2927 }
2928
2929 /* we did not miss a cut, good luck */
2930 return result;
2931 }
2932
2933 #if 0
2934 /* we don't need this, we actually do the right thing later */
2935 DNSName signer = getSigner(signatures);
2936
2937 if (!signer.empty() && name.isPartOf(signer)) {
2938 if (signer == best) {
2939 return result;
2940 }
2941 /* the zone cut is not the one we expected,
2942 this is fine because we will retrieve the needed DNSKEYs and DSs
2943 later, and even go Insecure if we missed a cut to Insecure (no DS)
2944 and the signatures do not validate (we should not go Bogus in that
2945 case) */
2946 }
2947 /* something is not right, but let's not worry about that for now.. */
2948 #endif
2949
2950 return result;
2951 }
2952
2953 vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth)
2954 {
2955 dsmap_t ds;
2956 if (signatures.empty()) {
2957 LOG(d_prefix<<": we have "<<std::to_string(dnskeys.size())<<" DNSKEYs but no signature, going Bogus!"<<endl);
2958 return vState::BogusNoRRSIG;
2959 }
2960
2961 DNSName signer = getSigner(signatures);
2962
2963 if (!signer.empty() && zone.isPartOf(signer)) {
2964 vState state = getDSRecords(signer, ds, false, depth);
2965
2966 if (state != vState::Secure) {
2967 return state;
2968 }
2969 }
2970 else {
2971 LOG(d_prefix<<": we have "<<std::to_string(dnskeys.size())<<" DNSKEYs but the zone ("<<zone<<") is not part of the signer ("<<signer<<"), check that we did not miss a zone cut"<<endl);
2972 /* try again to get the missed cuts, harder this time */
2973 auto zState = getValidationStatus(zone, false, false, depth);
2974 if (zState == vState::Secure) {
2975 /* too bad */
2976 LOG(d_prefix<<": after checking the zone cuts again, we still have "<<std::to_string(dnskeys.size())<<" DNSKEYs and the zone ("<<zone<<") is still not part of the signer ("<<signer<<"), going Bogus!"<<endl);
2977 return vState::BogusNoValidRRSIG;
2978 }
2979 else {
2980 return zState;
2981 }
2982 }
2983
2984 skeyset_t tentativeKeys;
2985 sortedRecords_t toSign;
2986
2987 for (const auto& dnskey : dnskeys) {
2988 if (dnskey.d_type == QType::DNSKEY) {
2989 auto content = getRR<DNSKEYRecordContent>(dnskey);
2990 if (content) {
2991 tentativeKeys.insert(content);
2992 toSign.insert(content);
2993 }
2994 }
2995 }
2996
2997 LOG(d_prefix<<": trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
2998 skeyset_t validatedKeys;
2999 auto state = validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
3000
3001 LOG(d_prefix<<": we now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
3002
3003 /* if we found at least one valid RRSIG covering the set,
3004 all tentative keys are validated keys. Otherwise it means
3005 we haven't found at least one DNSKEY and a matching RRSIG
3006 covering this set, this looks Bogus. */
3007 if (validatedKeys.size() != tentativeKeys.size()) {
3008 LOG(d_prefix<<": let's check whether we missed a zone cut before returning a Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
3009 /* try again to get the missed cuts, harder this time */
3010 auto zState = getValidationStatus(zone, false, false, depth);
3011 if (zState == vState::Secure) {
3012 /* too bad */
3013 LOG(d_prefix<<": after checking the zone cuts we are still in a Secure zone, returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
3014 return state;
3015 }
3016 else {
3017 return zState;
3018 }
3019 }
3020
3021 return state;
3022 }
3023
3024 vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth)
3025 {
3026 std::vector<DNSRecord> records;
3027 std::set<GetBestNSAnswer> beenthere;
3028 LOG(d_prefix<<"Retrieving DNSKeys for "<<signer<<endl);
3029
3030 vState state = vState::Indeterminate;
3031 const bool oldCacheOnly = setCacheOnly(false);
3032 int rcode = doResolve(signer, QType::DNSKEY, records, depth + 1, beenthere, state);
3033 setCacheOnly(oldCacheOnly);
3034
3035 if (rcode == RCode::ServFail) {
3036 throw ImmediateServFailException("Server Failure while retrieving DNSKEY records for " + signer.toLogString());
3037 }
3038
3039 if (rcode == RCode::NoError) {
3040 if (state == vState::Secure) {
3041 for (const auto& key : records) {
3042 if (key.d_type == QType::DNSKEY) {
3043 auto content = getRR<DNSKEYRecordContent>(key);
3044 if (content) {
3045 keys.insert(content);
3046 }
3047 }
3048 }
3049 }
3050 LOG(d_prefix<<"Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<state<<endl);
3051 return state;
3052 }
3053
3054 if (state == vState::Insecure) {
3055 return state;
3056 }
3057
3058 LOG(d_prefix<<"Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
3059 return vState::BogusUnableToGetDNSKEYs;
3060 }
3061
3062 vState SyncRes::validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType qtype, const DNSName& name, const QType type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures)
3063 {
3064 skeyset_t keys;
3065 if (signatures.empty()) {
3066 LOG(d_prefix<<"Bogus!"<<endl);
3067 return vState::BogusNoRRSIG;
3068 }
3069
3070 const DNSName signer = getSigner(signatures);
3071 bool dsFailed = false;
3072 if (!signer.empty() && name.isPartOf(signer)) {
3073 vState state = vState::Secure;
3074
3075 if ((qtype == QType::DNSKEY || qtype == QType::DS) && signer == qname) {
3076 /* we are already retrieving those keys, sorry */
3077 if (type == QType::DS && signer == name && !signer.isRoot()) {
3078 /* Unless we are getting the DS of the root zone, we should never see a
3079 DS (or a denial of a DS) signed by the DS itself, since we should be
3080 requesting it from the parent zone. Something is very wrong */
3081 LOG(d_prefix<<"The DS for "<<qname<<" is signed by itself"<<endl);
3082 state = vState::BogusSelfSignedDS;
3083 dsFailed = true;
3084 }
3085 else if (qtype == QType::DS && signer == qname && !signer.isRoot()) {
3086 if (type == QType::SOA || type == QType::NSEC || type == QType::NSEC3) {
3087 /* if we are trying to validate the DS or more likely NSEC(3)s proving that it does not exist, we have a problem.
3088 In that case let's go Bogus (we will check later if we missed a cut)
3089 */
3090 state = vState::BogusSelfSignedDS;
3091 dsFailed = true;
3092 }
3093 else if (type == QType::CNAME) {
3094 state = vState::BogusUnableToGetDSs;
3095 dsFailed = true;
3096 }
3097 }
3098 else if (qtype == QType::DNSKEY && signer == qname) {
3099 /* that actually does happen when a server returns NS records in authority
3100 along with the DNSKEY, leading us to trying to validate the RRSIGs for
3101 the NS with the DNSKEY that we are about to process. */
3102 if ((name == signer && type == QType::NSEC) || type == QType::NSEC3) {
3103 /* if we are trying to validate the DNSKEY (should not happen here),
3104 or more likely NSEC(3)s proving that it does not exist, we have a problem.
3105 In that case let's see if the DS does exist, and if it does let's go Bogus
3106 */
3107 dsmap_t results;
3108 vState dsState = getDSRecords(signer, results, false, depth, true);
3109 if (vStateIsBogus(dsState) || dsState == vState::Insecure) {
3110 state = dsState;
3111 if (vStateIsBogus(dsState)) {
3112 dsFailed = true;
3113 }
3114 }
3115 else {
3116 LOG(d_prefix<<"Unable to get the DS for "<<signer<<endl);
3117 state = vState::BogusUnableToGetDNSKEYs;
3118 dsFailed = true;
3119 }
3120 }
3121 else {
3122 /* return immediately since looking at the cuts is not going to change the
3123 fact that we are looking at a signature done with the key we are trying to
3124 obtain */
3125 LOG(d_prefix<<"we are looking at a signature done with the key we are trying to obtain "<<signer<<endl);
3126 return vState::Indeterminate;
3127 }
3128 }
3129 }
3130 if (state == vState::Secure) {
3131 LOG(d_prefix<<"retrieving the DNSKEYs for "<<signer<<endl);
3132 state = getDNSKeys(signer, keys, depth);
3133 }
3134
3135 if (state != vState::Secure) {
3136 if (!vStateIsBogus(state)) {
3137 return state;
3138 }
3139 /* try again to get the missed cuts, harder this time */
3140 LOG(d_prefix<<"checking whether we missed a zone cut for "<<signer<<" before returning a Bogus state for "<<name<<"|"<<type.toString()<<endl);
3141 auto zState = getValidationStatus(signer, false, dsFailed, depth);
3142 if (zState == vState::Secure) {
3143 /* too bad */
3144 LOG(d_prefix<<"we are still in a Secure zone, returning "<<vStateToString(state)<<endl);
3145 return state;
3146 }
3147 else {
3148 return zState;
3149 }
3150 }
3151 }
3152
3153 sortedRecords_t recordcontents;
3154 for (const auto& record : records) {
3155 recordcontents.insert(record.d_content);
3156 }
3157
3158 LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<"|"<<type.toString()<<endl);
3159 vState state = validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false);
3160 if (state == vState::Secure) {
3161 LOG(d_prefix<<"Secure!"<<endl);
3162 return vState::Secure;
3163 }
3164
3165 LOG(d_prefix<<vStateToString(state)<<"!"<<endl);
3166 /* try again to get the missed cuts, harder this time */
3167 auto zState = getValidationStatus(name, false, type == QType::DS, depth);
3168 LOG(d_prefix<<"checking whether we missed a zone cut before returning a Bogus state"<<endl);
3169 if (zState == vState::Secure) {
3170 /* too bad */
3171 LOG(d_prefix<<"we are still in a Secure zone, returning "<<vStateToString(state)<<endl);
3172 return state;
3173 }
3174 else {
3175 return zState;
3176 }
3177 }
3178
3179 /* This function will check whether the answer should have the AA bit set, and will set if it should be set and isn't.
3180 This is unfortunately needed to deal with very crappy so-called DNS servers */
3181 void SyncRes::fixupAnswer(const std::string& prefix, LWResult& lwr, const DNSName& qname, const QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery)
3182 {
3183 const bool wasForwardRecurse = wasForwarded && rdQuery;
3184
3185 if (wasForwardRecurse || lwr.d_aabit) {
3186 /* easy */
3187 return;
3188 }
3189
3190 for (const auto& rec : lwr.d_records) {
3191
3192 if (rec.d_type == QType::OPT) {
3193 continue;
3194 }
3195
3196 if (rec.d_class != QClass::IN) {
3197 continue;
3198 }
3199
3200 if (rec.d_type == QType::ANY) {
3201 continue;
3202 }
3203
3204 if (rec.d_place == DNSResourceRecord::ANSWER && (rec.d_type == qtype || rec.d_type == QType::CNAME || qtype == QType::ANY) && rec.d_name == qname && rec.d_name.isPartOf(auth)) {
3205 /* This is clearly an answer to the question we were asking, from an authoritative server that is allowed to send it.
3206 We are going to assume this server is broken and does not know it should set the AA bit, even though it is DNS 101 */
3207 LOG(prefix<<"Received a record for "<<rec.d_name<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<" in the answer section from "<<auth<<", without the AA bit set. Assuming this server is clueless and setting the AA bit."<<endl);
3208 lwr.d_aabit = true;
3209 return;
3210 }
3211
3212 if (rec.d_place != DNSResourceRecord::ANSWER) {
3213 /* we have scanned all the records in the answer section, if any, we are done */
3214 return;
3215 }
3216 }
3217 }
3218
3219 static void allowAdditionalEntry(std::unordered_set<DNSName>& allowedAdditionals, const DNSRecord& rec)
3220 {
3221 switch(rec.d_type) {
3222 case QType::MX:
3223 if (auto mxContent = getRR<MXRecordContent>(rec)) {
3224 allowedAdditionals.insert(mxContent->d_mxname);
3225 }
3226 break;
3227 case QType::NS:
3228 if (auto nsContent = getRR<NSRecordContent>(rec)) {
3229 allowedAdditionals.insert(nsContent->getNS());
3230 }
3231 break;
3232 case QType::SRV:
3233 if (auto srvContent = getRR<SRVRecordContent>(rec)) {
3234 allowedAdditionals.insert(srvContent->d_target);
3235 }
3236 break;
3237 case QType::SVCB: /* fall-through */
3238 case QType::HTTPS:
3239 if (auto svcbContent = getRR<SVCBBaseRecordContent>(rec)) {
3240 if (svcbContent->getPriority() > 0) {
3241 DNSName target = svcbContent->getTarget();
3242 if (target.isRoot()) {
3243 target = rec.d_name;
3244 }
3245 allowedAdditionals.insert(target);
3246 }
3247 else {
3248 // FIXME: Alias mode not implemented yet
3249 }
3250 }
3251 break;
3252 case QType::NAPTR:
3253 if (auto naptrContent = getRR<NAPTRRecordContent>(rec)) {
3254 auto flags = naptrContent->getFlags();
3255 toLowerInPlace(flags);
3256 if (flags.find('a') != string::npos || flags.find('s') != string::npos) {
3257 allowedAdditionals.insert(naptrContent->getReplacement());
3258 }
3259 }
3260 break;
3261 default:
3262 break;
3263 }
3264 }
3265
3266 void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery)
3267 {
3268 const bool wasForwardRecurse = wasForwarded && rdQuery;
3269 /* list of names for which we will allow A and AAAA records in the additional section
3270 to remain */
3271 std::unordered_set<DNSName> allowedAdditionals = { qname };
3272 bool haveAnswers = false;
3273 bool isNXDomain = false;
3274 bool isNXQType = false;
3275
3276 for(auto rec = lwr.d_records.begin(); rec != lwr.d_records.end(); ) {
3277
3278 if (rec->d_type == QType::OPT) {
3279 ++rec;
3280 continue;
3281 }
3282
3283 if (rec->d_class != QClass::IN) {
3284 LOG(prefix<<"Removing non internet-classed data received from "<<auth<<endl);
3285 rec = lwr.d_records.erase(rec);
3286 continue;
3287 }
3288
3289 if (rec->d_type == QType::ANY) {
3290 LOG(prefix<<"Removing 'ANY'-typed data received from "<<auth<<endl);
3291 rec = lwr.d_records.erase(rec);
3292 continue;
3293 }
3294
3295 if (!rec->d_name.isPartOf(auth)) {
3296 LOG(prefix<<"Removing record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
3297 rec = lwr.d_records.erase(rec);
3298 continue;
3299 }
3300
3301 /* dealing with the records in answer */
3302 if (!(lwr.d_aabit || wasForwardRecurse) && rec->d_place == DNSResourceRecord::ANSWER) {
3303 /* for now we allow a CNAME for the exact qname in ANSWER with AA=0, because Amazon DNS servers
3304 are sending such responses */
3305 if (!(rec->d_type == QType::CNAME && qname == rec->d_name)) {
3306 LOG(prefix<<"Removing record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the answer section without the AA bit set received from "<<auth<<endl);
3307 rec = lwr.d_records.erase(rec);
3308 continue;
3309 }
3310 }
3311
3312 if (rec->d_type == QType::DNAME && (rec->d_place != DNSResourceRecord::ANSWER || !qname.isPartOf(rec->d_name))) {
3313 LOG(prefix<<"Removing invalid DNAME record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
3314 rec = lwr.d_records.erase(rec);
3315 continue;
3316 }
3317
3318 if (rec->d_place == DNSResourceRecord::ANSWER && (qtype != QType::ANY && rec->d_type != qtype.getCode() && s_redirectionQTypes.count(rec->d_type) == 0 && rec->d_type != QType::SOA && rec->d_type != QType::RRSIG)) {
3319 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the ANSWER section received from "<<auth<<endl);
3320 rec = lwr.d_records.erase(rec);
3321 continue;
3322 }
3323
3324 if (rec->d_place == DNSResourceRecord::ANSWER && !haveAnswers) {
3325 haveAnswers = true;
3326 }
3327
3328 if (rec->d_place == DNSResourceRecord::ANSWER) {
3329 allowAdditionalEntry(allowedAdditionals, *rec);
3330 }
3331
3332 /* dealing with the records in authority */
3333 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type != QType::NS && rec->d_type != QType::DS && rec->d_type != QType::SOA && rec->d_type != QType::RRSIG && rec->d_type != QType::NSEC && rec->d_type != QType::NSEC3) {
3334 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the AUTHORITY section received from "<<auth<<endl);
3335 rec = lwr.d_records.erase(rec);
3336 continue;
3337 }
3338
3339 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::SOA) {
3340 if (!qname.isPartOf(rec->d_name)) {
3341 LOG(prefix<<"Removing irrelevant SOA record '"<<rec->d_name<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the AUTHORITY section received from "<<auth<<endl);
3342 rec = lwr.d_records.erase(rec);
3343 continue;
3344 }
3345
3346 if (!(lwr.d_aabit || wasForwardRecurse)) {
3347 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the AUTHORITY section received from "<<auth<<endl);
3348 rec = lwr.d_records.erase(rec);
3349 continue;
3350 }
3351
3352 if (!haveAnswers) {
3353 if (lwr.d_rcode == RCode::NXDomain) {
3354 isNXDomain = true;
3355 }
3356 else if (lwr.d_rcode == RCode::NoError) {
3357 isNXQType = true;
3358 }
3359 }
3360 }
3361
3362 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::NS && (isNXDomain || isNXQType)) {
3363 /*
3364 * We don't want to pick up NS records in AUTHORITY and their ADDITIONAL sections of NXDomain answers
3365 * because they are somewhat easy to insert into a large, fragmented UDP response
3366 * for an off-path attacker by injecting spoofed UDP fragments. So do not add these to allowedAdditionals.
3367 */
3368 LOG(prefix<<"Removing NS record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section of a "<<(isNXDomain ? "NXD" : "NXQTYPE")<<" response received from "<<auth<<endl);
3369 rec = lwr.d_records.erase(rec);
3370 continue;
3371 }
3372
3373 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::NS && !d_updatingRootNS && rec->d_name == g_rootdnsname) {
3374 /*
3375 * We don't want to pick up root NS records in AUTHORITY and their associated ADDITIONAL sections of random queries.
3376 * So don't add them to allowedAdditionals.
3377 */
3378 LOG(prefix<<"Removing NS record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section of a response received from "<<auth<<endl);
3379 rec = lwr.d_records.erase(rec);
3380 continue;
3381 }
3382
3383 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::NS) {
3384 allowAdditionalEntry(allowedAdditionals, *rec);
3385 }
3386
3387 /* dealing with the records in additional */
3388 if (rec->d_place == DNSResourceRecord::ADDITIONAL && rec->d_type != QType::A && rec->d_type != QType::AAAA && rec->d_type != QType::RRSIG) {
3389 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the ADDITIONAL section received from "<<auth<<endl);
3390 rec = lwr.d_records.erase(rec);
3391 continue;
3392 }
3393
3394 if (rec->d_place == DNSResourceRecord::ADDITIONAL && allowedAdditionals.count(rec->d_name) == 0) {
3395 LOG(prefix<<"Removing irrelevant additional record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the ADDITIONAL section received from "<<auth<<endl);
3396 rec = lwr.d_records.erase(rec);
3397 continue;
3398 }
3399
3400 ++rec;
3401 }
3402 }
3403
3404 RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType qtype, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, vState& state, bool& needWildcardProof, bool& gatherWildcardProof, unsigned int& wildcardLabelsCount, bool rdQuery, const ComboAddress& remoteIP)
3405 {
3406 bool wasForwardRecurse = wasForwarded && rdQuery;
3407 tcache_t tcache;
3408
3409 string prefix;
3410 if(doLog()) {
3411 prefix=d_prefix;
3412 prefix.append(depth, ' ');
3413 }
3414
3415 fixupAnswer(prefix, lwr, qname, qtype, auth, wasForwarded, rdQuery);
3416 sanitizeRecords(prefix, lwr, qname, qtype, auth, wasForwarded, rdQuery);
3417
3418 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
3419 const unsigned int labelCount = qname.countLabels();
3420 bool isCNAMEAnswer = false;
3421 bool isDNAMEAnswer = false;
3422 DNSName seenAuth;
3423
3424 for (auto& rec : lwr.d_records) {
3425 if (rec.d_type == QType::OPT || rec.d_class != QClass::IN) {
3426 continue;
3427 }
3428
3429 rec.d_ttl = min(s_maxcachettl, rec.d_ttl);
3430
3431 if (!isCNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::CNAME && (!(qtype==QType::CNAME)) && rec.d_name == qname && !isDNAMEAnswer) {
3432 isCNAMEAnswer = true;
3433 }
3434 if (!isDNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::DNAME && qtype != QType::DNAME && qname.isPartOf(rec.d_name)) {
3435 isDNAMEAnswer = true;
3436 isCNAMEAnswer = false;
3437 }
3438
3439 if (rec.d_type == QType::SOA && rec.d_place == DNSResourceRecord::AUTHORITY && qname.isPartOf(rec.d_name)) {
3440 seenAuth = rec.d_name;
3441 }
3442
3443 if (rec.d_type == QType::RRSIG) {
3444 auto rrsig = getRR<RRSIGRecordContent>(rec);
3445 if (rrsig) {
3446 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
3447 count can be lower than the name's label count if it was
3448 synthesized from the wildcard. Note that the difference might
3449 be > 1. */
3450 if (rec.d_name == qname && isWildcardExpanded(labelCount, rrsig)) {
3451 gatherWildcardProof = true;
3452 if (!isWildcardExpandedOntoItself(rec.d_name, labelCount, rrsig)) {
3453 /* if we have a wildcard expanded onto itself, we don't need to prove
3454 that the exact name doesn't exist because it actually does.
3455 We still want to gather the corresponding NSEC/NSEC3 records
3456 to pass them to our client in case it wants to validate by itself.
3457 */
3458 LOG(prefix<<qname<<": RRSIG indicates the name was synthesized from a wildcard, we need a wildcard proof"<<endl);
3459 needWildcardProof = true;
3460 }
3461 else {
3462 LOG(prefix<<qname<<": RRSIG indicates the name was synthesized from a wildcard expanded onto itself, we need to gather wildcard proof"<<endl);
3463 }
3464 wildcardLabelsCount = rrsig->d_labels;
3465 }
3466
3467 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"' and place "<<rec.d_place<<endl;
3468 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
3469 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signaturesTTL = std::min(tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signaturesTTL, rec.d_ttl);
3470 }
3471 }
3472 }
3473
3474 /* if we have a positive answer synthesized from a wildcard,
3475 we need to store the corresponding NSEC/NSEC3 records proving
3476 that the exact name did not exist in the negative cache */
3477 if (gatherWildcardProof) {
3478 for (const auto& rec : lwr.d_records) {
3479 if (rec.d_type == QType::OPT || rec.d_class != QClass::IN) {
3480 continue;
3481 }
3482
3483 if (nsecTypes.count(rec.d_type)) {
3484 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
3485 }
3486 else if (rec.d_type == QType::RRSIG) {
3487 auto rrsig = getRR<RRSIGRecordContent>(rec);
3488 if (rrsig && nsecTypes.count(rrsig->d_type)) {
3489 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
3490 }
3491 }
3492 }
3493 }
3494
3495 // reap all answers from this packet that are acceptable
3496 for (auto& rec : lwr.d_records) {
3497 if(rec.d_type == QType::OPT) {
3498 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
3499 continue;
3500 }
3501
3502 LOG(prefix<<qname<<": accept answer '"<<rec.d_name<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"|"<<rec.d_content->getZoneRepresentation()<<"' from '"<<auth<<"' nameservers? ttl="<<rec.d_ttl<<", place="<<(int)rec.d_place<<" ");
3503
3504 // We called sanitizeRecords before, so all ANY, non-IN and non-aa/non-forwardrecurse answer records are already removed
3505
3506 if(rec.d_name.isPartOf(auth)) {
3507 if (rec.d_type == QType::RRSIG) {
3508 LOG("RRSIG - separate"<<endl);
3509 }
3510 else if (rec.d_type == QType::DS && rec.d_name == auth) {
3511 LOG("NO - DS provided by child zone"<<endl);
3512 }
3513 else {
3514 bool haveLogged = false;
3515 if (isDNAMEAnswer && rec.d_type == QType::CNAME) {
3516 LOG("NO - we already have a DNAME answer for this domain"<<endl);
3517 continue;
3518 }
3519 if (!t_sstorage.domainmap->empty()) {
3520 // Check if we are authoritative for a zone in this answer
3521 DNSName tmp_qname(rec.d_name);
3522 // We may be auth for domain example.com, but the DS record needs to come from the parent (.com) nameserver
3523 if (rec.d_type == QType::DS) {
3524 tmp_qname.chopOff();
3525 }
3526 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
3527 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
3528 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
3529 if (auth_domain_iter->first != auth) {
3530 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
3531 continue;
3532 } else {
3533 LOG("YES! - This answer was ");
3534 if (!wasForwarded) {
3535 LOG("retrieved from the local auth store.");
3536 } else {
3537 LOG("received from a server we forward to.");
3538 }
3539 haveLogged = true;
3540 LOG(endl);
3541 }
3542 }
3543 }
3544 if (!haveLogged) {
3545 LOG("YES!"<<endl);
3546 }
3547
3548 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
3549
3550 DNSRecord dr(rec);
3551 dr.d_ttl += d_now.tv_sec;
3552 dr.d_place=DNSResourceRecord::ANSWER;
3553 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
3554 }
3555 }
3556 else
3557 LOG("NO!"<<endl);
3558 }
3559
3560 // supplant
3561 for (auto& entry : tcache) {
3562 if ((entry.second.records.size() + entry.second.signatures.size() + authorityRecs.size()) > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
3563 uint32_t lowestTTD = computeLowestTTD(entry.second.records, entry.second.signatures, entry.second.signaturesTTL, authorityRecs);
3564
3565 for (auto& record : entry.second.records) {
3566 record.d_ttl = lowestTTD; // boom
3567 }
3568 }
3569
3570 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
3571 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
3572 }
3573
3574 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
3575
3576 if (i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
3577 continue;
3578
3579 /* Even if the AA bit is set, additional data cannot be considered
3580 as authoritative. This is especially important during validation
3581 because keeping records in the additional section is allowed even
3582 if the corresponding RRSIGs are not included, without setting the TC
3583 bit, as stated in rfc4035's section 3.1.1. Including RRSIG RRs in a Response:
3584 "When placing a signed RRset in the Additional section, the name
3585 server MUST also place its RRSIG RRs in the Additional section.
3586 If space does not permit inclusion of both the RRset and its
3587 associated RRSIG RRs, the name server MAY retain the RRset while
3588 dropping the RRSIG RRs. If this happens, the name server MUST NOT
3589 set the TC bit solely because these RRSIG RRs didn't fit."
3590 */
3591 bool isAA = lwr.d_aabit && i->first.place != DNSResourceRecord::ADDITIONAL;
3592 /* if we forwarded the query to a recursor, we can expect the answer to be signed,
3593 even if the answer is not AA. Of course that's not only true inside a Secure
3594 zone, but we check that below. */
3595 bool expectSignature = i->first.place == DNSResourceRecord::ANSWER || ((lwr.d_aabit || wasForwardRecurse) && i->first.place != DNSResourceRecord::ADDITIONAL);
3596 /* in a non authoritative answer, we only care about the DS record (or lack of) */
3597 if (!isAA && (i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
3598 expectSignature = true;
3599 }
3600
3601 if (isCNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER || i->first.type != QType::CNAME || i->first.name != qname)) {
3602 /*
3603 rfc2181 states:
3604 Note that the answer section of an authoritative answer normally
3605 contains only authoritative data. However when the name sought is an
3606 alias (see section 10.1.1) only the record describing that alias is
3607 necessarily authoritative. Clients should assume that other records
3608 may have come from the server's cache. Where authoritative answers
3609 are required, the client should query again, using the canonical name
3610 associated with the alias.
3611 */
3612 isAA = false;
3613 expectSignature = false;
3614 }
3615 else if (isDNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER || i->first.type != QType::DNAME || !qname.isPartOf(i->first.name))) {
3616 /* see above */
3617 isAA = false;
3618 expectSignature = false;
3619 }
3620
3621 if ((isCNAMEAnswer || isDNAMEAnswer) && i->first.place == DNSResourceRecord::AUTHORITY && i->first.type == QType::NS && auth == i->first.name) {
3622 /* These NS can't be authoritative since we have a CNAME/DNAME answer for which (see above) only the
3623 record describing that alias is necessarily authoritative.
3624 But if we allow the current auth, which might be serving the child zone, to raise the TTL
3625 of non-authoritative NS in the cache, they might be able to keep a "ghost" zone alive forever,
3626 even after the delegation is gone from the parent.
3627 So let's just do nothing with them, we can fetch them directly if we need them.
3628 */
3629 LOG(d_prefix<<": skipping authority NS from '"<<auth<<"' nameservers in CNAME/DNAME answer "<<i->first.name<<"|"<<DNSRecordContent::NumberToType(i->first.type)<<endl);
3630 continue;
3631 }
3632
3633 /*
3634 * RFC 6672 section 5.3.1
3635 * In any response, a signed DNAME RR indicates a non-terminal
3636 * redirection of the query. There might or might not be a server-
3637 * synthesized CNAME in the answer section; if there is, the CNAME will
3638 * never be signed. For a DNSSEC validator, verification of the DNAME
3639 * RR and then that the CNAME was properly synthesized is sufficient
3640 * proof.
3641 *
3642 * We do the synthesis check in processRecords, here we make sure we
3643 * don't validate the CNAME.
3644 */
3645 if (isDNAMEAnswer && i->first.type == QType::CNAME) {
3646 expectSignature = false;
3647 }
3648
3649 vState recordState = vState::Indeterminate;
3650
3651 if (expectSignature && shouldValidate()) {
3652 vState initialState = getValidationStatus(i->first.name, !i->second.signatures.empty(), i->first.type == QType::DS, depth);
3653 LOG(d_prefix<<": got initial zone status "<<initialState<<" for record "<<i->first.name<<"|"<<DNSRecordContent::NumberToType(i->first.type)<<endl);
3654
3655 if (initialState == vState::Secure) {
3656 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER && i->first.name == getSigner(i->second.signatures)) {
3657 LOG(d_prefix<<"Validating DNSKEY for "<<i->first.name<<endl);
3658 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth);
3659 }
3660 else {
3661 LOG(d_prefix<<"Validating non-additional "<<QType(i->first.type).toString()<<" record for "<<i->first.name<<endl);
3662 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, QType(i->first.type), i->second.records, i->second.signatures);
3663 }
3664 }
3665 else {
3666 recordState = initialState;
3667 LOG(d_prefix<<"Skipping validation because the current state is "<<recordState<<endl);
3668 }
3669
3670 LOG(d_prefix<<"Validation result is "<<recordState<<", current state is "<<state<<endl);
3671 if (state != recordState) {
3672 updateValidationState(state, recordState);
3673 }
3674 }
3675
3676 if (vStateIsBogus(recordState)) {
3677 /* this is a TTD by now, be careful */
3678 for(auto& record : i->second.records) {
3679 record.d_ttl = std::min(record.d_ttl, static_cast<uint32_t>(s_maxbogusttl + d_now.tv_sec));
3680 }
3681 }
3682
3683 /* We don't need to store NSEC3 records in the positive cache because:
3684 - we don't allow direct NSEC3 queries
3685 - denial of existence proofs in wildcard expanded positive responses are stored in authorityRecs
3686 - denial of existence proofs for negative responses are stored in the negative cache
3687 We also don't want to cache non-authoritative data except for:
3688 - records coming from non forward-recurse servers (those will never be AA)
3689 - DS (special case)
3690 - NS, A and AAAA (used for infra queries)
3691 */
3692 if (i->first.type != QType::NSEC3 && (i->first.type == QType::DS || i->first.type == QType::NS || i->first.type == QType::A || i->first.type == QType::AAAA || isAA || wasForwardRecurse)) {
3693
3694 bool doCache = true;
3695 if (i->first.place == DNSResourceRecord::ANSWER && ednsmask) {
3696 const bool isv4 = ednsmask->isIPv4();
3697 if ((isv4 && s_ecsipv4nevercache) || (!isv4 && s_ecsipv6nevercache)) {
3698 doCache = false;
3699 }
3700 // If ednsmask is relevant, we do not want to cache if the scope prefix length is large and TTL is small
3701 if (doCache && s_ecscachelimitttl > 0) {
3702 bool manyMaskBits = (isv4 && ednsmask->getBits() > s_ecsipv4cachelimit) ||
3703 (!isv4 && ednsmask->getBits() > s_ecsipv6cachelimit);
3704
3705 if (manyMaskBits) {
3706 uint32_t minttl = UINT32_MAX;
3707 for (const auto &it : i->second.records) {
3708 if (it.d_ttl < minttl)
3709 minttl = it.d_ttl;
3710 }
3711 bool ttlIsSmall = minttl < s_ecscachelimitttl + d_now.tv_sec;
3712 if (ttlIsSmall) {
3713 // Case: many bits and ttlIsSmall
3714 doCache = false;
3715 }
3716 }
3717 }
3718 }
3719
3720 d_fromAuthIP = remoteIP;
3721
3722 if (doCache) {
3723 g_recCache->replace(d_now.tv_sec, i->first.name, i->first.type, i->second.records, i->second.signatures, authorityRecs, i->first.type == QType::DS ? true : isAA, auth, i->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none, d_routingTag, recordState, remoteIP);
3724
3725 if (g_aggressiveNSECCache && needWildcardProof && recordState == vState::Secure && i->first.place == DNSResourceRecord::ANSWER && i->first.name == qname && !i->second.signatures.empty() && !d_routingTag && !ednsmask) {
3726 /* we have an answer synthesized from a wildcard and aggressive NSEC is enabled, we need to store the
3727 wildcard in its non-expanded form in the cache to be able to synthesize wildcard answers later */
3728 const auto& rrsig = i->second.signatures.at(0);
3729
3730 if (isWildcardExpanded(labelCount, rrsig) && !isWildcardExpandedOntoItself(i->first.name, labelCount, rrsig)) {
3731 DNSName realOwner = getNSECOwnerName(i->first.name, i->second.signatures);
3732
3733 std::vector<DNSRecord> content;
3734 content.reserve(i->second.records.size());
3735 for (const auto& record : i->second.records) {
3736 DNSRecord nonExpandedRecord(record);
3737 nonExpandedRecord.d_name = realOwner;
3738 content.push_back(std::move(nonExpandedRecord));
3739 }
3740
3741 g_recCache->replace(d_now.tv_sec, realOwner, QType(i->first.type), content, i->second.signatures, /* no additional records in that case */ {}, i->first.type == QType::DS ? true : isAA, auth, boost::none, boost::none, recordState, remoteIP);
3742 }
3743 }
3744 }
3745 }
3746
3747 if (seenAuth.empty() && !i->second.signatures.empty()) {
3748 seenAuth = getSigner(i->second.signatures);
3749 }
3750
3751 if (g_aggressiveNSECCache && (i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && recordState == vState::Secure && !seenAuth.empty()) {
3752 // Good candidate for NSEC{,3} caching
3753 g_aggressiveNSECCache->insertNSEC(seenAuth, i->first.name, i->second.records.at(0), i->second.signatures, i->first.type == QType::NSEC3);
3754 }
3755
3756 if (i->first.place == DNSResourceRecord::ANSWER && ednsmask) {
3757 d_wasVariable=true;
3758 }
3759 }
3760
3761 return RCode::NoError;
3762 }
3763
3764 void SyncRes::updateDenialValidationState(vState& neValidationState, const DNSName& neName, vState& state, const dState denialState, const dState expectedState, bool isDS, unsigned int depth)
3765 {
3766 if (denialState == expectedState) {
3767 neValidationState = vState::Secure;
3768 }
3769 else {
3770 if (denialState == dState::OPTOUT) {
3771 LOG(d_prefix<<"OPT-out denial found for "<<neName<<endl);
3772 /* rfc5155 states:
3773 "The AD bit, as defined by [RFC4035], MUST NOT be set when returning a
3774 response containing a closest (provable) encloser proof in which the
3775 NSEC3 RR that covers the "next closer" name has the Opt-Out bit set.
3776
3777 This rule is based on what this closest encloser proof actually
3778 proves: names that would be covered by the Opt-Out NSEC3 RR may or
3779 may not exist as insecure delegations. As such, not all the data in
3780 responses containing such closest encloser proofs will have been
3781 cryptographically verified, so the AD bit cannot be set."
3782
3783 At best the Opt-Out NSEC3 RR proves that there is no signed DS (so no
3784 secure delegation).
3785 */
3786 neValidationState = vState::Insecure;
3787 }
3788 else if (denialState == dState::INSECURE) {
3789 LOG(d_prefix<<"Insecure denial found for "<<neName<<", returning Insecure"<<endl);
3790 neValidationState = vState::Insecure;
3791 }
3792 else {
3793 LOG(d_prefix<<"Invalid denial found for "<<neName<<", res="<<denialState<<", expectedState="<<expectedState<<", checking whether we have missed a zone cut before returning a Bogus state"<<endl);
3794 /* try again to get the missed cuts, harder this time */
3795 auto zState = getValidationStatus(neName, false, isDS, depth);
3796 if (zState != vState::Secure) {
3797 neValidationState = zState;
3798 }
3799 else {
3800 LOG(d_prefix<<"Still in a secure zone with an invalid denial for "<<neName<<", returning "<<vStateToString(vState::BogusInvalidDenial)<<endl);
3801 neValidationState = vState::BogusInvalidDenial;
3802 }
3803 }
3804 }
3805 updateValidationState(state, neValidationState);
3806 }
3807
3808 dState SyncRes::getDenialValidationState(const NegCache::NegCacheEntry& ne, const dState expectedState, bool referralToUnsigned)
3809 {
3810 cspmap_t csp = harvestCSPFromNE(ne);
3811 return getDenial(csp, ne.d_name, ne.d_qtype.getCode(), referralToUnsigned, expectedState == dState::NXQTYPE);
3812 }
3813
3814 bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, const QType qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, const bool needWildcardProof, const bool gatherWildcardProof, const unsigned int wildcardLabelsCount, int& rcode, bool& negIndicHasSignatures, unsigned int depth)
3815 {
3816 bool done = false;
3817 DNSName dnameTarget, dnameOwner;
3818 uint32_t dnameTTL = 0;
3819 bool referralOnDS = false;
3820
3821 for (auto& rec : lwr.d_records) {
3822 if (rec.d_type != QType::OPT && rec.d_class != QClass::IN) {
3823 continue;
3824 }
3825
3826 if (rec.d_place == DNSResourceRecord::ANSWER && !(lwr.d_aabit || sendRDQuery)) {
3827 /* for now we allow a CNAME for the exact qname in ANSWER with AA=0, because Amazon DNS servers
3828 are sending such responses */
3829 if (!(rec.d_type == QType::CNAME && rec.d_name == qname)) {
3830 continue;
3831 }
3832 }
3833 const bool negCacheIndiction = rec.d_place == DNSResourceRecord::AUTHORITY && rec.d_type == QType::SOA &&
3834 lwr.d_rcode == RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth);
3835
3836 bool putInNegCache = true;
3837 if (negCacheIndiction && qtype == QType::DS && isForwardOrAuth(qname)) {
3838 // #10189, a NXDOMAIN to a DS query for a forwarded or auth domain should not NXDOMAIN the whole domain
3839 putInNegCache = false;
3840 }
3841
3842 if (negCacheIndiction) {
3843 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
3844
3845 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
3846 // only add a SOA if we're not going anywhere after this
3847 if (newtarget.empty()) {
3848 ret.push_back(rec);
3849 }
3850
3851 NegCache::NegCacheEntry ne;
3852
3853 uint32_t lowestTTL = rec.d_ttl;
3854 /* if we get an NXDomain answer with a CNAME, the name
3855 does exist but the target does not */
3856 ne.d_name = newtarget.empty() ? qname : newtarget;
3857 ne.d_qtype = QType::ENT; // this encodes 'whole record'
3858 ne.d_auth = rec.d_name;
3859 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
3860
3861 if (vStateIsBogus(state)) {
3862 ne.d_validationState = state;
3863 }
3864 else {
3865 /* here we need to get the validation status of the zone telling us that the domain does not
3866 exist, ie the owner of the SOA */
3867 auto recordState = getValidationStatus(rec.d_name, !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty(), false, depth);
3868 if (recordState == vState::Secure) {
3869 dState denialState = getDenialValidationState(ne, dState::NXDOMAIN, false);
3870 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, dState::NXDOMAIN, false, depth);
3871 }
3872 else {
3873 ne.d_validationState = recordState;
3874 updateValidationState(state, ne.d_validationState);
3875 }
3876 }
3877
3878 if (vStateIsBogus(ne.d_validationState)) {
3879 lowestTTL = min(lowestTTL, s_maxbogusttl);
3880 }
3881
3882 ne.d_ttd = d_now.tv_sec + lowestTTL;
3883 /* if we get an NXDomain answer with a CNAME, let's not cache the
3884 target, even the server was authoritative for it,
3885 and do an additional query for the CNAME target.
3886 We have a regression test making sure we do exactly that.
3887 */
3888 if (newtarget.empty() && putInNegCache) {
3889 g_negCache->add(ne);
3890 if (s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot() && lwr.d_aabit) {
3891 ne.d_name = ne.d_name.getLastLabel();
3892 g_negCache->add(ne);
3893 }
3894 }
3895
3896 negIndicHasSignatures = !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty();
3897 negindic = true;
3898 }
3899 else if (rec.d_place == DNSResourceRecord::ANSWER && s_redirectionQTypes.count(rec.d_type) > 0 && // CNAME or DNAME answer
3900 s_redirectionQTypes.count(qtype.getCode()) == 0) { // But not in response to a CNAME or DNAME query
3901 if (rec.d_type == QType::CNAME && rec.d_name == qname) {
3902 if (!dnameOwner.empty()) { // We synthesize ourselves
3903 continue;
3904 }
3905 ret.push_back(rec);
3906 if (auto content = getRR<CNAMERecordContent>(rec)) {
3907 newtarget = DNSName(content->getTarget());
3908 }
3909 } else if (rec.d_type == QType::DNAME && qname.isPartOf(rec.d_name)) { // DNAME
3910 ret.push_back(rec);
3911 if (auto content = getRR<DNAMERecordContent>(rec)) {
3912 dnameOwner = rec.d_name;
3913 dnameTarget = content->getTarget();
3914 dnameTTL = rec.d_ttl;
3915 if (!newtarget.empty()) { // We had a CNAME before, remove it from ret so we don't cache it
3916 ret.erase(std::remove_if(
3917 ret.begin(),
3918 ret.end(),
3919 [&qname](DNSRecord& rr) {
3920 return (rr.d_place == DNSResourceRecord::ANSWER && rr.d_type == QType::CNAME && rr.d_name == qname);
3921 }),
3922 ret.end());
3923 }
3924 try {
3925 newtarget = qname.makeRelative(dnameOwner) + dnameTarget;
3926 } catch (const std::exception &e) {
3927 // We should probably catch an std::range_error here and set the rcode to YXDOMAIN (RFC 6672, section 2.2)
3928 // But there is no way to set the RCODE from this function
3929 throw ImmediateServFailException("Unable to perform DNAME substitution(DNAME owner: '" + dnameOwner.toLogString() +
3930 "', DNAME target: '" + dnameTarget.toLogString() + "', substituted name: '" +
3931 qname.makeRelative(dnameOwner).toLogString() + "." + dnameTarget.toLogString() +
3932 "' : " + e.what());
3933 }
3934 }
3935 }
3936 }
3937 /* if we have a positive answer synthesized from a wildcard, we need to
3938 return the corresponding NSEC/NSEC3 records from the AUTHORITY section
3939 proving that the exact name did not exist.
3940 Except if this is a NODATA answer because then we will gather the NXNSEC records later */
3941 else if (gatherWildcardProof && !negindic && (rec.d_type == QType::RRSIG || rec.d_type == QType::NSEC || rec.d_type == QType::NSEC3) && rec.d_place == DNSResourceRecord::AUTHORITY) {
3942 ret.push_back(rec); // enjoy your DNSSEC
3943 }
3944 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
3945 else if (rec.d_place == DNSResourceRecord::ANSWER && rec.d_name == qname &&
3946 (
3947 rec.d_type == qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType::ANY)
3948 )
3949 )
3950 {
3951 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
3952
3953 done = true;
3954 rcode = RCode::NoError;
3955
3956 if (needWildcardProof) {
3957 /* positive answer synthesized from a wildcard */
3958 NegCache::NegCacheEntry ne;
3959 ne.d_name = qname;
3960 ne.d_qtype = QType::ENT; // this encodes 'whole record'
3961 uint32_t lowestTTL = rec.d_ttl;
3962 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
3963
3964 if (vStateIsBogus(state)) {
3965 ne.d_validationState = state;
3966 }
3967 else {
3968 auto recordState = getValidationStatus(qname, !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty(), false, depth);
3969
3970 if (recordState == vState::Secure) {
3971 /* We have a positive answer synthesized from a wildcard, we need to check that we have
3972 proof that the exact name doesn't exist so the wildcard can be used,
3973 as described in section 5.3.4 of RFC 4035 and 5.3 of RFC 7129.
3974 */
3975 cspmap_t csp = harvestCSPFromNE(ne);
3976 dState res = getDenial(csp, qname, ne.d_qtype.getCode(), false, false, false, wildcardLabelsCount);
3977 if (res != dState::NXDOMAIN) {
3978 vState st = vState::BogusInvalidDenial;
3979 if (res == dState::INSECURE || res == dState::OPTOUT) {
3980 /* Some part could not be validated, for example a NSEC3 record with a too large number of iterations,
3981 this is not enough to warrant a Bogus, but go Insecure. */
3982 st = vState::Insecure;
3983 LOG(d_prefix<<"Unable to validate denial in wildcard expanded positive response found for "<<qname<<", returning Insecure, res="<<res<<endl);
3984 }
3985 else {
3986 LOG(d_prefix<<"Invalid denial in wildcard expanded positive response found for "<<qname<<", returning Bogus, res="<<res<<endl);
3987 rec.d_ttl = std::min(rec.d_ttl, s_maxbogusttl);
3988 }
3989
3990 updateValidationState(state, st);
3991 /* we already stored the record with a different validation status, let's fix it */
3992 updateValidationStatusInCache(qname, qtype, lwr.d_aabit, st);
3993 }
3994 }
3995 }
3996 }
3997
3998 ret.push_back(rec);
3999 }
4000 else if ((rec.d_type == QType::RRSIG || rec.d_type == QType::NSEC || rec.d_type == QType::NSEC3) && rec.d_place == DNSResourceRecord::ANSWER) {
4001 if (rec.d_type != QType::RRSIG || rec.d_name == qname) {
4002 ret.push_back(rec); // enjoy your DNSSEC
4003 } else if (rec.d_type == QType::RRSIG && qname.isPartOf(rec.d_name)) {
4004 auto rrsig = getRR<RRSIGRecordContent>(rec);
4005 if (rrsig != nullptr && rrsig->d_type == QType::DNAME) {
4006 ret.push_back(rec);
4007 }
4008 }
4009 }
4010 else if (rec.d_place == DNSResourceRecord::AUTHORITY && rec.d_type == QType::NS && qname.isPartOf(rec.d_name)) {
4011 if (moreSpecificThan(rec.d_name,auth)) {
4012 newauth = rec.d_name;
4013 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
4014
4015 /* check if we have a referral from the parent zone to a child zone for a DS query, which is not right */
4016 if (qtype == QType::DS && (newauth.isPartOf(qname) || qname == newauth)) {
4017 /* just got a referral from the parent zone when asking for a DS, looks like this server did not get the DNSSEC memo.. */
4018 referralOnDS = true;
4019 }
4020 else {
4021 realreferral = true;
4022 if (auto content = getRR<NSRecordContent>(rec)) {
4023 nsset.insert(content->getNS());
4024 }
4025 }
4026 }
4027 else {
4028 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
4029 if (auto content = getRR<NSRecordContent>(rec)) {
4030 nsset.insert(content->getNS());
4031 }
4032 }
4033 }
4034 else if (rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
4035 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
4036 }
4037 else if (realreferral && rec.d_place == DNSResourceRecord::AUTHORITY && (rec.d_type == QType::NSEC || rec.d_type == QType::NSEC3) && newauth.isPartOf(auth)) {
4038 /* we might have received a denial of the DS, let's check */
4039 NegCache::NegCacheEntry ne;
4040 uint32_t lowestTTL = rec.d_ttl;
4041 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
4042
4043 if (!vStateIsBogus(state)) {
4044 auto recordState = getValidationStatus(newauth, !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty(), true, depth);
4045
4046 if (recordState == vState::Secure) {
4047 ne.d_auth = auth;
4048 ne.d_name = newauth;
4049 ne.d_qtype = QType::DS;
4050 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
4051
4052 dState denialState = getDenialValidationState(ne, dState::NXQTYPE, true);
4053
4054 if (denialState == dState::NXQTYPE || denialState == dState::OPTOUT || denialState == dState::INSECURE) {
4055 ne.d_ttd = lowestTTL + d_now.tv_sec;
4056 ne.d_validationState = vState::Secure;
4057 if (denialState == dState::OPTOUT) {
4058 ne.d_validationState = vState::Insecure;
4059 }
4060 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
4061
4062 g_negCache->add(ne);
4063
4064 /* Careful! If the client is asking for a DS that does not exist, we need to provide the SOA along with the NSEC(3) proof
4065 and we might not have it if we picked up the proof from a delegation, in which case we need to keep on to do the actual DS
4066 query. */
4067 if (qtype == QType::DS && qname == newauth && (d_externalDSQuery.empty() || qname != d_externalDSQuery)) {
4068 /* we are actually done! */
4069 negindic = true;
4070 negIndicHasSignatures = !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty();
4071 nsset.clear();
4072 }
4073 }
4074 }
4075 }
4076 }
4077 else if (!done && rec.d_place == DNSResourceRecord::AUTHORITY && rec.d_type == QType::SOA &&
4078 lwr.d_rcode == RCode::NoError && qname.isPartOf(rec.d_name)) {
4079 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype<<"'"<<endl);
4080
4081 if (!newtarget.empty()) {
4082 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
4083 }
4084 else {
4085 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
4086
4087 NegCache::NegCacheEntry ne;
4088 ne.d_auth = rec.d_name;
4089 uint32_t lowestTTL = rec.d_ttl;
4090 ne.d_name = qname;
4091 ne.d_qtype = qtype;
4092 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
4093
4094 if (vStateIsBogus(state)) {
4095 ne.d_validationState = state;
4096 }
4097 else {
4098 auto recordState = getValidationStatus(qname, !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty(), qtype == QType::DS, depth);
4099 if (recordState == vState::Secure) {
4100 dState denialState = getDenialValidationState(ne, dState::NXQTYPE, false);
4101 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, dState::NXQTYPE, qtype == QType::DS, depth);
4102 } else {
4103 ne.d_validationState = recordState;
4104 updateValidationState(state, ne.d_validationState);
4105 }
4106 }
4107
4108 if (vStateIsBogus(ne.d_validationState)) {
4109 lowestTTL = min(lowestTTL, s_maxbogusttl);
4110 rec.d_ttl = min(rec.d_ttl, s_maxbogusttl);
4111 }
4112 ne.d_ttd = d_now.tv_sec + lowestTTL;
4113
4114 if (qtype.getCode()) { // prevents us from NXDOMAIN'ing a whole domain
4115 g_negCache->add(ne);
4116 }
4117
4118 ret.push_back(rec);
4119 negindic = true;
4120 negIndicHasSignatures = !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty();
4121 }
4122 }
4123 }
4124
4125 if (!dnameTarget.empty()) {
4126 // Synthesize a CNAME
4127 auto cnamerec = DNSRecord();
4128 cnamerec.d_name = qname;
4129 cnamerec.d_type = QType::CNAME;
4130 cnamerec.d_ttl = dnameTTL;
4131 cnamerec.d_content = std::make_shared<CNAMERecordContent>(CNAMERecordContent(newtarget));
4132 ret.push_back(std::move(cnamerec));
4133 }
4134
4135 /* If we have seen a proper denial, let's forget that we also had a referral for a DS query.
4136 Otherwise we need to deal with it. */
4137 if (referralOnDS && !negindic) {
4138 LOG(prefix<<qname<<": got a referral to the child zone for a DS query without a negative indication (missing SOA in authority), treating that as a NODATA"<<endl);
4139 if (!vStateIsBogus(state)) {
4140 auto recordState = getValidationStatus(qname, false, true, depth);
4141 if (recordState == vState::Secure) {
4142 /* we are in a secure zone, got a referral to the child zone on a DS query, no denial, that's wrong */
4143 LOG(prefix<<qname<<": NODATA without a negative indication (missing SOA in authority) in a DNSSEC secure zone, going Bogus"<<endl);
4144 updateValidationState(state, vState::BogusMissingNegativeIndication);
4145 }
4146 }
4147 negindic = true;
4148 negIndicHasSignatures = false;
4149 }
4150
4151 return done;
4152 }
4153
4154 bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed)
4155 {
4156 bool chained = false;
4157 LWResult::Result resolveret = LWResult::Result::Success;
4158 s_outqueries++;
4159 d_outqueries++;
4160
4161 if(d_outqueries + d_throttledqueries > s_maxqperq) {
4162 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
4163 }
4164
4165 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
4166 throw ImmediateServFailException("Too much time waiting for "+qname.toLogString()+"|"+qtype.toString()+", timeouts: "+std::to_string(d_timeouts) +", throttles: "+std::to_string(d_throttledqueries) + ", queries: "+std::to_string(d_outqueries)+", "+std::to_string(d_totUsec/1000)+"msec");
4167 }
4168
4169 if(doTCP) {
4170 if (doDoT) {
4171 LOG(prefix<<qname<<": using DoT with "<< remoteIP.toStringWithPort() <<endl);
4172 s_dotoutqueries++;
4173 d_dotoutqueries++;
4174 } else {
4175 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
4176 s_tcpoutqueries++;
4177 d_tcpoutqueries++;
4178 }
4179 }
4180
4181 int preOutQueryRet = RCode::NoError;
4182 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, preOutQueryRet, d_eventTrace)) {
4183 LOG(prefix<<qname<<": query handled by Lua"<<endl);
4184 }
4185 else {
4186 ednsmask=getEDNSSubnetMask(qname, remoteIP);
4187 if(ednsmask) {
4188 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
4189 s_ecsqueries++;
4190 }
4191 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, auth, qtype.getCode(),
4192 doTCP, sendRDQuery, &d_now, ednsmask, &lwr, &chained, nsName); // <- we go out on the wire!
4193 if(ednsmask) {
4194 s_ecsresponses++;
4195 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
4196 if (ednsmask->getBits() > 0) {
4197 if (ednsmask->isIPv4()) {
4198 ++SyncRes::s_ecsResponsesBySubnetSize4.at(ednsmask->getBits()-1);
4199 }
4200 else {
4201 ++SyncRes::s_ecsResponsesBySubnetSize6.at(ednsmask->getBits()-1);
4202 }
4203 }
4204 }
4205 }
4206
4207 /* preoutquery killed the query by setting dq.rcode to -3 */
4208 if (preOutQueryRet == -3) {
4209 throw ImmediateServFailException("Query killed by policy");
4210 }
4211
4212 d_totUsec += lwr.d_usec;
4213 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
4214
4215 bool dontThrottle = false;
4216 {
4217 auto dontThrottleNames = g_dontThrottleNames.getLocal();
4218 auto dontThrottleNetmasks = g_dontThrottleNetmasks.getLocal();
4219 dontThrottle = dontThrottleNames->check(nsName) || dontThrottleNetmasks->match(remoteIP);
4220 }
4221
4222 if (resolveret != LWResult::Result::Success) {
4223 /* Error while resolving */
4224 if (resolveret == LWResult::Result::Timeout) {
4225 /* Time out */
4226
4227 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
4228 d_timeouts++;
4229 s_outgoingtimeouts++;
4230
4231 if(remoteIP.sin4.sin_family == AF_INET)
4232 s_outgoing4timeouts++;
4233 else
4234 s_outgoing6timeouts++;
4235
4236 if(t_timeouts)
4237 t_timeouts->push_back(remoteIP);
4238 }
4239 else if (resolveret == LWResult::Result::OSLimitError) {
4240 /* OS resource limit reached */
4241 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
4242 g_stats.resourceLimits++;
4243 }
4244 else if (resolveret == LWResult::Result::Spoofed) {
4245 spoofed = true;
4246 }
4247 else {
4248 /* LWResult::Result::PermanentError */
4249 s_unreachables++;
4250 d_unreachables++;
4251 // XXX questionable use of errno
4252 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<stringerror()<< endl);
4253 }
4254
4255 if (resolveret != LWResult::Result::OSLimitError && !chained && !dontThrottle) {
4256 // don't account for resource limits, they are our own fault
4257 // And don't throttle when the IP address is on the dontThrottleNetmasks list or the name is part of dontThrottleNames
4258 t_sstorage.nsSpeeds[nsName.empty()? DNSName(remoteIP.toStringWithPort()) : nsName].submit(remoteIP, 1000000, d_now); // 1 sec
4259
4260 // code below makes sure we don't filter COM or the root
4261 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && s_fails.lock()->incr(remoteIP, d_now) >= s_serverdownmaxfails) {
4262 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
4263 // mark server as down
4264 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(remoteIP, g_rootdnsname, 0), s_serverdownthrottletime, 10000);
4265 }
4266 else if (resolveret == LWResult::Result::PermanentError) {
4267 // unreachable, 1 minute or 100 queries
4268 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
4269 }
4270 else {
4271 // timeout, 10 seconds or 5 queries
4272 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
4273 }
4274 }
4275
4276 return false;
4277 }
4278
4279 if (lwr.d_validpacket == false) {
4280 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a packet we could not parse over " << (doTCP ? "TCP" : "UDP") << ", trying sibling IP or NS"<<endl);
4281 if (!chained && !dontThrottle) {
4282
4283 // let's make sure we prefer a different server for some time, if there is one available
4284 t_sstorage.nsSpeeds[nsName.empty()? DNSName(remoteIP.toStringWithPort()) : nsName].submit(remoteIP, 1000000, d_now); // 1 sec
4285
4286 if (doTCP) {
4287 // we can be more heavy-handed over TCP
4288 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(remoteIP, qname, qtype.getCode()), 60, 10);
4289 }
4290 else {
4291 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(remoteIP, qname, qtype.getCode()), 10, 2);
4292 }
4293 }
4294 return false;
4295 }
4296 else {
4297 /* we got an answer */
4298 if (lwr.d_rcode != RCode::NoError && lwr.d_rcode != RCode::NXDomain) {
4299 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< RCode::to_s(lwr.d_rcode) << ", trying sibling IP or NS"<<endl);
4300 if (!chained && !dontThrottle) {
4301 if (wasForwarded && lwr.d_rcode == RCode::ServFail) {
4302 // rather than throttling what could be the only server we have for this destination, let's make sure we try a different one if there is one available
4303 // on the other hand, we might keep hammering a server under attack if there is no other alternative, or the alternative is overwhelmed as well, but
4304 // at the very least we will detect that if our packets stop being answered
4305 t_sstorage.nsSpeeds[nsName.empty()? DNSName(remoteIP.toStringWithPort()) : nsName].submit(remoteIP, 1000000, d_now); // 1 sec
4306 }
4307 else {
4308 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
4309 }
4310 }
4311 return false;
4312 }
4313 }
4314
4315 /* this server sent a valid answer, mark it backup up if it was down */
4316 if(s_serverdownmaxfails > 0) {
4317 s_fails.lock()->clear(remoteIP);
4318 }
4319
4320 if (lwr.d_tcbit) {
4321 truncated = true;
4322
4323 if (doTCP) {
4324 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
4325 if (!dontThrottle) {
4326 /* let's treat that as a ServFail answer from this server */
4327 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
4328 }
4329 return false;
4330 }
4331 LOG(prefix<<qname<<": truncated bit set, over UDP"<<endl);
4332
4333 return true;
4334 }
4335
4336 return true;
4337 }
4338
4339 void SyncRes::handleNewTarget(const std::string& prefix, const DNSName& qname, const DNSName& newtarget, const QType qtype, std::vector<DNSRecord>& ret, int& rcode, int depth, const std::vector<DNSRecord>& recordsFromAnswer, vState& state)
4340 {
4341 if (newtarget == qname) {
4342 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
4343 ret.clear();
4344 rcode = RCode::ServFail;
4345 return;
4346 }
4347 if (newtarget.isPartOf(qname)) {
4348 // a.b.c. CNAME x.a.b.c will go to great depths with QM on
4349 LOG(prefix<<qname<<": status=got a CNAME referral to child, disabling QM"<<endl);
4350 setQNameMinimization(false);
4351 }
4352
4353 if (depth > 10) {
4354 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
4355 rcode = RCode::ServFail;
4356 return;
4357 }
4358
4359 if (!d_followCNAME) {
4360 rcode = RCode::NoError;
4361 return;
4362 }
4363
4364 // Check to see if we already have seen the new target as a previous target
4365 if (scanForCNAMELoop(newtarget, ret)) {
4366 LOG(prefix<<qname<<": status=got a CNAME referral that causes a loop, returning SERVFAIL"<<endl);
4367 ret.clear();
4368 rcode = RCode::ServFail;
4369 return;
4370 }
4371
4372 if (qtype == QType::DS || qtype == QType::DNSKEY) {
4373 LOG(prefix<<qname<<": status=got a CNAME referral, but we are looking for a DS or DNSKEY"<<endl);
4374
4375 if (d_doDNSSEC) {
4376 addNXNSECS(ret, recordsFromAnswer);
4377 }
4378
4379 rcode = RCode::NoError;
4380 return;
4381 }
4382
4383 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
4384
4385 set<GetBestNSAnswer> beenthere;
4386 vState cnameState = vState::Indeterminate;
4387 rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere, cnameState);
4388 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<state<<" with the state from the CNAME quest: "<<cnameState<<endl);
4389 updateValidationState(state, cnameState);
4390 }
4391
4392 bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const ComboAddress& remoteIP)
4393 {
4394 string prefix;
4395 if(doLog()) {
4396 prefix=d_prefix;
4397 prefix.append(depth, ' ');
4398 }
4399
4400 if(s_minimumTTL) {
4401 for(auto& rec : lwr.d_records) {
4402 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
4403 }
4404 }
4405
4406 /* if the answer is ECS-specific, a minimum TTL is set for this kind of answers
4407 and it's higher than the global minimum TTL */
4408 if (ednsmask && s_minimumECSTTL > 0 && (s_minimumTTL == 0 || s_minimumECSTTL > s_minimumTTL)) {
4409 for(auto& rec : lwr.d_records) {
4410 if (rec.d_place == DNSResourceRecord::ANSWER) {
4411 rec.d_ttl = max(rec.d_ttl, s_minimumECSTTL);
4412 }
4413 }
4414 }
4415
4416 bool needWildcardProof = false;
4417 bool gatherWildcardProof = false;
4418 unsigned int wildcardLabelsCount;
4419 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, needWildcardProof, gatherWildcardProof, wildcardLabelsCount, sendRDQuery, remoteIP);
4420 if (*rcode != RCode::NoError) {
4421 return true;
4422 }
4423
4424 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
4425
4426 set<DNSName> nsset;
4427 bool realreferral = false;
4428 bool negindic = false;
4429 bool negIndicHasSignatures = false;
4430 DNSName newauth;
4431 DNSName newtarget;
4432
4433 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof, gatherWildcardProof, wildcardLabelsCount, *rcode, negIndicHasSignatures, depth);
4434
4435 if (done){
4436 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
4437 LOG(prefix<<qname<<": validation status is "<<state<<endl);
4438 return true;
4439 }
4440
4441 if (!newtarget.empty()) {
4442 handleNewTarget(prefix, qname, newtarget, qtype.getCode(), ret, *rcode, depth, lwr.d_records, state);
4443 return true;
4444 }
4445
4446 if (lwr.d_rcode == RCode::NXDomain) {
4447 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
4448
4449 auto tempState = getValidationStatus(qname, negIndicHasSignatures, qtype == QType::DS, depth);
4450 if (tempState == vState::Secure && (lwr.d_aabit || sendRDQuery) && !negindic) {
4451 LOG(prefix<<qname<<": NXDOMAIN without a negative indication (missing SOA in authority) in a DNSSEC secure zone, going Bogus"<<endl);
4452 updateValidationState(state, vState::BogusMissingNegativeIndication);
4453 }
4454 else if (state == vState::Indeterminate) {
4455 /* we might not have validated any record, because we did get a NXDOMAIN without any SOA
4456 from an insecure zone, for example */
4457 updateValidationState(state, tempState);
4458 }
4459
4460 if (d_doDNSSEC) {
4461 addNXNSECS(ret, lwr.d_records);
4462 }
4463
4464 *rcode = RCode::NXDomain;
4465 return true;
4466 }
4467
4468 if (nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
4469 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
4470
4471 auto tempState = getValidationStatus(qname, negIndicHasSignatures, qtype == QType::DS, depth);
4472 if (tempState == vState::Secure && (lwr.d_aabit || sendRDQuery) && !negindic) {
4473 LOG(prefix<<qname<<": NODATA without a negative indication (missing SOA in authority) in a DNSSEC secure zone, going Bogus"<<endl);
4474 updateValidationState(state, vState::BogusMissingNegativeIndication);
4475 }
4476 else if (state == vState::Indeterminate) {
4477 /* we might not have validated any record, because we did get a NODATA without any SOA
4478 from an insecure zone, for example */
4479 updateValidationState(state, tempState);
4480 }
4481
4482 if (d_doDNSSEC) {
4483 addNXNSECS(ret, lwr.d_records);
4484 }
4485
4486 *rcode = RCode::NoError;
4487 return true;
4488 }
4489
4490 if(realreferral) {
4491 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
4492
4493 nameservers.clear();
4494 for (auto const &nameserver : nsset) {
4495 if (d_wantsRPZ && !d_appliedPolicy.wasHit()) {
4496 bool match = dfe.getProcessingPolicy(nameserver, d_discardedPolicies, d_appliedPolicy);
4497 if (match) {
4498 mergePolicyTags(d_policyTags, d_appliedPolicy.getTags());
4499 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
4500 if (d_pdl && d_pdl->policyHitEventFilter(d_requestor, qname, qtype, d_queryReceivedOverTCP, d_appliedPolicy, d_policyTags, d_discardedPolicies)) {
4501 /* reset to no match */
4502 d_appliedPolicy = DNSFilterEngine::Policy();
4503 }
4504 else {
4505 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<d_appliedPolicy.getName()<<"'"<<endl);
4506 throw PolicyHitException();
4507 }
4508 }
4509 }
4510 }
4511 nameservers.insert({nameserver, {{}, false}});
4512 }
4513 LOG("looping to them"<<endl);
4514 *gotNewServers = true;
4515 auth=newauth;
4516
4517 return false;
4518 }
4519
4520 return false;
4521 }
4522
4523 bool SyncRes::doDoTtoAuth(const DNSName& ns) const
4524 {
4525 return g_DoTToAuthNames.getLocal()->check(ns);
4526 }
4527
4528 /** returns:
4529 * -1 in case of no results
4530 * rcode otherwise
4531 */
4532 int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType qtype,
4533 vector<DNSRecord>&ret,
4534 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state, StopAtDelegation* stopAtDelegation)
4535 {
4536 auto luaconfsLocal = g_luaconfs.getLocal();
4537 string prefix;
4538 if(doLog()) {
4539 prefix=d_prefix;
4540 prefix.append(depth, ' ');
4541 }
4542
4543 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
4544
4545 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
4546 /* RPZ hit */
4547 if (d_pdl && d_pdl->policyHitEventFilter(d_requestor, qname, qtype, d_queryReceivedOverTCP, d_appliedPolicy, d_policyTags, d_discardedPolicies)) {
4548 /* reset to no match */
4549 d_appliedPolicy = DNSFilterEngine::Policy();
4550 }
4551 else {
4552 throw PolicyHitException();
4553 }
4554 }
4555
4556 LOG(endl);
4557
4558 unsigned int addressQueriesForNS = 0;
4559 for(;;) { // we may get more specific nameservers
4560 auto rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
4561
4562 // We allow s_maxnsaddressqperq (default 10) queries with empty responses when resolving NS names.
4563 // If a zone publishes many (more than s_maxnsaddressqperq) NS records, we allow less.
4564 // This is to "punish" zones that publish many non-resolving NS names.
4565 // We always allow 5 NS name resolving attempts with empty results.
4566 unsigned int nsLimit = s_maxnsaddressqperq;
4567 if (rnameservers.size() > nsLimit) {
4568 int newLimit = static_cast<int>(nsLimit) - (rnameservers.size() - nsLimit);
4569 nsLimit = std::max(5, newLimit);
4570 }
4571
4572 for(auto tns=rnameservers.cbegin();;++tns) {
4573 if (addressQueriesForNS >= nsLimit) {
4574 throw ImmediateServFailException(std::to_string(nsLimit)+" (adjusted max-ns-address-qperq) or more queries with empty results for NS addresses sent resolving "+qname.toLogString());
4575 }
4576 if(tns==rnameservers.cend()) {
4577 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
4578 if(!auth.isRoot() && flawedNSSet) {
4579 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
4580
4581 if(g_recCache->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
4582 g_stats.nsSetInvalidations++;
4583 }
4584 return -1;
4585 }
4586
4587 bool cacheOnly = false;
4588 // this line needs to identify the 'self-resolving' behaviour
4589 if(qname == tns->first && (qtype.getCode() == QType::A || qtype.getCode() == QType::AAAA)) {
4590 /* we might have a glue entry in cache so let's try this NS
4591 but only if we have enough in the cache to know how to reach it */
4592 LOG(prefix<<qname<<": Using NS to resolve itself, but only using what we have in cache ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
4593 cacheOnly = true;
4594 }
4595
4596 typedef vector<ComboAddress> remoteIPs_t;
4597 remoteIPs_t remoteIPs;
4598 remoteIPs_t::iterator remoteIP;
4599 bool pierceDontQuery=false;
4600 bool sendRDQuery=false;
4601 boost::optional<Netmask> ednsmask;
4602 LWResult lwr;
4603 const bool wasForwarded = tns->first.empty() && (!nameservers[tns->first].first.empty());
4604 int rcode = RCode::NoError;
4605 bool gotNewServers = false;
4606
4607 if (tns->first.empty() && !wasForwarded) {
4608 static ComboAddress const s_oobRemote("255.255.255.255");
4609 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
4610 /* setting state to indeterminate since validation is disabled for local auth zone,
4611 and Insecure would be misleading. */
4612 state = vState::Indeterminate;
4613 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
4614 lwr.d_tcbit=false;
4615 lwr.d_aabit=true;
4616
4617 /* we have received an answer, are we done ? */
4618 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state, s_oobRemote);
4619 if (done) {
4620 return rcode;
4621 }
4622 if (gotNewServers) {
4623 if (stopAtDelegation && *stopAtDelegation == Stop) {
4624 *stopAtDelegation = Stopped;
4625 return rcode;
4626 }
4627 break;
4628 }
4629 }
4630 else {
4631 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
4632 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly, addressQueriesForNS);
4633
4634 if(remoteIPs.empty()) {
4635 LOG(prefix<<qname<<": Failed to get IP for NS "<<tns->first<<", trying next if available"<<endl);
4636 flawedNSSet=true;
4637 continue;
4638 }
4639 else {
4640 bool hitPolicy{false};
4641 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<tns->first<<" to: ");
4642 for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) {
4643 if(remoteIP != remoteIPs.begin()) {
4644 LOG(", ");
4645 }
4646 LOG(remoteIP->toString());
4647 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
4648 hitPolicy = true;
4649 }
4650 }
4651 LOG(endl);
4652 if (hitPolicy) { //implies d_wantsRPZ
4653 /* RPZ hit */
4654 if (d_pdl && d_pdl->policyHitEventFilter(d_requestor, qname, qtype, d_queryReceivedOverTCP, d_appliedPolicy, d_policyTags, d_discardedPolicies)) {
4655 /* reset to no match */
4656 d_appliedPolicy = DNSFilterEngine::Policy();
4657 }
4658 else {
4659 throw PolicyHitException();
4660 }
4661 }
4662 }
4663
4664 for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) {
4665 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype<<"'"<<endl);
4666
4667 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
4668 continue;
4669 }
4670
4671 bool truncated = false;
4672 bool spoofed = false;
4673 bool gotAnswer = false;
4674 bool doDoT = false;
4675
4676 if (doDoTtoAuth(tns->first)) {
4677 remoteIP->setPort(853);
4678 doDoT = true;
4679 }
4680 if (SyncRes::s_dot_to_port_853 && remoteIP->getPort() == 853) {
4681 doDoT = true;
4682 }
4683 bool forceTCP = doDoT;
4684
4685 if (!forceTCP) {
4686 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery, wasForwarded,
4687 tns->first, *remoteIP, false, false, truncated, spoofed);
4688 }
4689 if (forceTCP || (spoofed || (gotAnswer && truncated))) {
4690 /* retry, over TCP this time */
4691 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery, wasForwarded,
4692 tns->first, *remoteIP, true, doDoT, truncated, spoofed);
4693 }
4694
4695 if (!gotAnswer) {
4696 continue;
4697 }
4698
4699 LOG(prefix<<qname<<": Got "<<(unsigned int)lwr.d_records.size()<<" answers from "<<tns->first<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
4700
4701 /* // for you IPv6 fanatics :-)
4702 if(remoteIP->sin4.sin_family==AF_INET6)
4703 lwr.d_usec/=3;
4704 */
4705 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
4706
4707 t_sstorage.nsSpeeds[tns->first.empty()? DNSName(remoteIP->toStringWithPort()) : tns->first].submit(*remoteIP, lwr.d_usec, d_now);
4708
4709 /* we have received an answer, are we done ? */
4710 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state, *remoteIP);
4711 if (done) {
4712 return rcode;
4713 }
4714 if (gotNewServers) {
4715 if (stopAtDelegation && *stopAtDelegation == Stop) {
4716 *stopAtDelegation = Stopped;
4717 return rcode;
4718 }
4719 break;
4720 }
4721 /* was lame */
4722 t_sstorage.throttle.throttle(d_now.tv_sec, std::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
4723 }
4724
4725 if (gotNewServers) {
4726 break;
4727 }
4728
4729 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
4730 continue;
4731
4732 }
4733 }
4734 }
4735 return -1;
4736 }
4737
4738 void SyncRes::setQuerySource(const ComboAddress& requestor, boost::optional<const EDNSSubnetOpts&> incomingECS)
4739 {
4740 d_requestor = requestor;
4741
4742 if (incomingECS && incomingECS->source.getBits() > 0) {
4743 d_cacheRemote = incomingECS->source.getMaskedNetwork();
4744 uint8_t bits = std::min(incomingECS->source.getBits(), (incomingECS->source.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
4745 ComboAddress trunc = incomingECS->source.getNetwork();
4746 trunc.truncate(bits);
4747 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
4748 } else {
4749 d_cacheRemote = d_requestor;
4750 if(!incomingECS && s_ednslocalsubnets.match(d_requestor)) {
4751 ComboAddress trunc = d_requestor;
4752 uint8_t bits = d_requestor.isIPv4() ? 32 : 128;
4753 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
4754 trunc.truncate(bits);
4755 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
4756 } else if (s_ecsScopeZero.source.getBits() > 0) {
4757 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0.
4758 But using an empty ECS in that case would mean inserting
4759 a non ECS-specific entry into the cache, preventing any further
4760 ECS-specific query to be sent.
4761 So instead we use the trick described in section 7.1.2:
4762 "The subsequent Recursive Resolver query to the Authoritative Nameserver
4763 will then either not include an ECS option or MAY optionally include
4764 its own address information, which is what the Authoritative
4765 Nameserver will almost certainly use to generate any Tailored
4766 Response in lieu of an option. This allows the answer to be handled
4767 by the same caching mechanism as other queries, with an explicit
4768 indicator of the applicable scope. Subsequent Stub Resolver queries
4769 for /0 can then be answered from this cached response.
4770 */
4771 d_outgoingECSNetwork = boost::optional<Netmask>(s_ecsScopeZero.source.getMaskedNetwork());
4772 d_cacheRemote = s_ecsScopeZero.source.getNetwork();
4773 } else {
4774 // ECS disabled because no scope-zero address could be derived.
4775 d_outgoingECSNetwork = boost::none;
4776 }
4777 }
4778 }
4779
4780 boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const DNSName& dn, const ComboAddress& rem)
4781 {
4782 if(d_outgoingECSNetwork && (s_ednsdomains.check(dn) || s_ednsremotesubnets.match(rem))) {
4783 return d_outgoingECSNetwork;
4784 }
4785 return boost::none;
4786 }
4787
4788 void SyncRes::parseEDNSSubnetAllowlist(const std::string& alist)
4789 {
4790 vector<string> parts;
4791 stringtok(parts, alist, ",; ");
4792 for(const auto& a : parts) {
4793 try {
4794 s_ednsremotesubnets.addMask(Netmask(a));
4795 }
4796 catch(...) {
4797 s_ednsdomains.add(DNSName(a));
4798 }
4799 }
4800 }
4801
4802 void SyncRes::parseEDNSSubnetAddFor(const std::string& subnetlist)
4803 {
4804 vector<string> parts;
4805 stringtok(parts, subnetlist, ",; ");
4806 for(const auto& a : parts) {
4807 s_ednslocalsubnets.addMask(a);
4808 }
4809 }
4810
4811 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_recursor.cc
4812 int directResolve(const DNSName& qname, const QType qtype, const QClass qclass, vector<DNSRecord>& ret, shared_ptr<RecursorLua4> pdl)
4813 {
4814 return directResolve(qname, qtype, qclass, ret, pdl, SyncRes::s_qnameminimization);
4815 }
4816
4817 int directResolve(const DNSName& qname, const QType qtype, const QClass qclass, vector<DNSRecord>& ret, shared_ptr<RecursorLua4> pdl, bool qm)
4818 {
4819 struct timeval now;
4820 gettimeofday(&now, 0);
4821
4822 SyncRes sr(now);
4823 sr.setQNameMinimization(qm);
4824 if (pdl) {
4825 sr.setLuaEngine(pdl);
4826 }
4827
4828 int res = -1;
4829 try {
4830 res = sr.beginResolve(qname, qtype, qclass, ret, 0);
4831 }
4832 catch(const PDNSException& e) {
4833 g_log<<Logger::Error<<"Failed to resolve "<<qname<<", got pdns exception: "<<e.reason<<endl;
4834 ret.clear();
4835 }
4836 catch(const ImmediateServFailException& e) {
4837 g_log<<Logger::Error<<"Failed to resolve "<<qname<<", got ImmediateServFailException: "<<e.reason<<endl;
4838 ret.clear();
4839 }
4840 catch(const PolicyHitException& e) {
4841 g_log<<Logger::Error<<"Failed to resolve "<<qname<<", got a policy hit"<<endl;
4842 ret.clear();
4843 }
4844 catch(const std::exception& e) {
4845 g_log<<Logger::Error<<"Failed to resolve "<<qname<<", got STL error: "<<e.what()<<endl;
4846 ret.clear();
4847 }
4848 catch(...) {
4849 g_log<<Logger::Error<<"Failed to resolve "<<qname<<", got an exception"<<endl;
4850 ret.clear();
4851 }
4852
4853 return res;
4854 }
4855
4856 int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback, unsigned int depth) {
4857 SyncRes sr(now);
4858 sr.setDoEDNS0(true);
4859 sr.setUpdatingRootNS();
4860 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
4861 sr.setDNSSECValidationRequested(g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate);
4862 sr.setAsyncCallback(asyncCallback);
4863
4864 vector<DNSRecord> ret;
4865 int res = -1;
4866 try {
4867 res = sr.beginResolve(g_rootdnsname, QType::NS, 1, ret, depth + 1);
4868 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
4869 auto state = sr.getValidationState();
4870 if (vStateIsBogus(state)) {
4871 throw PDNSException("Got Bogus validation result for .|NS");
4872 }
4873 }
4874 }
4875 catch(const PDNSException& e) {
4876 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
4877 }
4878 catch(const ImmediateServFailException& e) {
4879 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
4880 }
4881 catch(const PolicyHitException& e) {
4882 g_log<<Logger::Error<<"Failed to update . records, got a policy hit"<<endl;
4883 ret.clear();
4884 }
4885 catch(const std::exception& e) {
4886 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
4887 }
4888 catch(...) {
4889 g_log<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
4890 }
4891
4892 if (res == 0) {
4893 g_log<<Logger::Debug<<"Refreshed . records"<<endl;
4894 }
4895 else {
4896 g_log<<Logger::Warning<<"Failed to update root NS records, RCODE="<<res<<endl;
4897 }
4898 return res;
4899 }