]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/syncres.cc
wip
[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 "cachecleaner.hh"
28 #include "dns_random.hh"
29 #include "dnsparser.hh"
30 #include "dnsrecords.hh"
31 #include "ednssubnet.hh"
32 #include "logger.hh"
33 #include "lua-recursor4.hh"
34 #include "rec-lua-conf.hh"
35 #include "syncres.hh"
36 #include "dnsseckeeper.hh"
37 #include "validate-recursor.hh"
38
39 thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage;
40 thread_local std::unique_ptr<addrringbuf_t> t_timeouts;
41
42 std::unordered_set<DNSName> SyncRes::s_delegationOnly;
43 std::unique_ptr<NetmaskGroup> SyncRes::s_dontQuery{nullptr};
44 NetmaskGroup SyncRes::s_ednslocalsubnets;
45 NetmaskGroup SyncRes::s_ednsremotesubnets;
46 SuffixMatchNode SyncRes::s_ednsdomains;
47 EDNSSubnetOpts SyncRes::s_ecsScopeZero;
48 string SyncRes::s_serverID;
49 SyncRes::LogMode SyncRes::s_lm;
50 const std::unordered_set<uint16_t> SyncRes::s_redirectionQTypes = {QType::CNAME, QType::DNAME};
51
52 unsigned int SyncRes::s_maxnegttl;
53 unsigned int SyncRes::s_maxbogusttl;
54 unsigned int SyncRes::s_maxcachettl;
55 unsigned int SyncRes::s_maxqperq;
56 unsigned int SyncRes::s_maxtotusec;
57 unsigned int SyncRes::s_maxdepth;
58 unsigned int SyncRes::s_minimumTTL;
59 unsigned int SyncRes::s_minimumECSTTL;
60 unsigned int SyncRes::s_packetcachettl;
61 unsigned int SyncRes::s_packetcacheservfailttl;
62 unsigned int SyncRes::s_serverdownmaxfails;
63 unsigned int SyncRes::s_serverdownthrottletime;
64 unsigned int SyncRes::s_ecscachelimitttl;
65 std::atomic<uint64_t> SyncRes::s_authzonequeries;
66 std::atomic<uint64_t> SyncRes::s_queries;
67 std::atomic<uint64_t> SyncRes::s_outgoingtimeouts;
68 std::atomic<uint64_t> SyncRes::s_outgoing4timeouts;
69 std::atomic<uint64_t> SyncRes::s_outgoing6timeouts;
70 std::atomic<uint64_t> SyncRes::s_outqueries;
71 std::atomic<uint64_t> SyncRes::s_tcpoutqueries;
72 std::atomic<uint64_t> SyncRes::s_throttledqueries;
73 std::atomic<uint64_t> SyncRes::s_dontqueries;
74 std::atomic<uint64_t> SyncRes::s_qnameminfallbacksuccess;
75 std::atomic<uint64_t> SyncRes::s_nodelegated;
76 std::atomic<uint64_t> SyncRes::s_unreachables;
77 std::atomic<uint64_t> SyncRes::s_ecsqueries;
78 std::atomic<uint64_t> SyncRes::s_ecsresponses;
79 std::map<uint8_t, std::atomic<uint64_t>> SyncRes::s_ecsResponsesBySubnetSize4;
80 std::map<uint8_t, std::atomic<uint64_t>> SyncRes::s_ecsResponsesBySubnetSize6;
81
82 uint8_t SyncRes::s_ecsipv4limit;
83 uint8_t SyncRes::s_ecsipv6limit;
84 uint8_t SyncRes::s_ecsipv4cachelimit;
85 uint8_t SyncRes::s_ecsipv6cachelimit;
86
87 bool SyncRes::s_doIPv6;
88 bool SyncRes::s_nopacketcache;
89 bool SyncRes::s_rootNXTrust;
90 bool SyncRes::s_noEDNS;
91 bool SyncRes::s_qnameminimization;
92 SyncRes::HardenNXD SyncRes::s_hardenNXD;
93
94 #define LOG(x) if(d_lm == Log) { g_log <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
95
96 static void accountAuthLatency(int usec, int family)
97 {
98 if(family == AF_INET) {
99 if(usec < 1000)
100 g_stats.auth4Answers0_1++;
101 else if(usec < 10000)
102 g_stats.auth4Answers1_10++;
103 else if(usec < 100000)
104 g_stats.auth4Answers10_100++;
105 else if(usec < 1000000)
106 g_stats.auth4Answers100_1000++;
107 else
108 g_stats.auth4AnswersSlow++;
109 } else {
110 if(usec < 1000)
111 g_stats.auth6Answers0_1++;
112 else if(usec < 10000)
113 g_stats.auth6Answers1_10++;
114 else if(usec < 100000)
115 g_stats.auth6Answers10_100++;
116 else if(usec < 1000000)
117 g_stats.auth6Answers100_1000++;
118 else
119 g_stats.auth6AnswersSlow++;
120 }
121
122 }
123
124
125 SyncRes::SyncRes(const struct timeval& now) : d_authzonequeries(0), d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
126 d_totUsec(0), d_now(now),
127 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_qNameMinimization(s_qnameminimization), d_lm(s_lm)
128
129 {
130 }
131
132 /** everything begins here - this is the entry point just after receiving a packet */
133 int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
134 {
135 vState state = Indeterminate;
136 s_queries++;
137 d_wasVariable=false;
138 d_wasOutOfBand=false;
139
140 if (doSpecialNamesResolve(qname, qtype, qclass, ret)) {
141 d_queryValidationState = Insecure; // this could fool our stats into thinking a validation took place
142 return 0; // so do check before updating counters (we do now)
143 }
144
145 auto qtypeCode = qtype.getCode();
146 /* rfc6895 section 3.1 */
147 if ((qtypeCode >= 128 && qtypeCode <= 254) || qtypeCode == QType::RRSIG || qtypeCode == QType::NSEC3 || qtypeCode == QType::OPT || qtypeCode == 65535) {
148 return -1;
149 }
150
151 if(qclass==QClass::ANY)
152 qclass=QClass::IN;
153 else if(qclass!=QClass::IN)
154 return -1;
155
156 set<GetBestNSAnswer> beenthere;
157 int res=doResolve(qname, qtype, ret, 0, beenthere, state);
158 d_queryValidationState = state;
159
160 if (shouldValidate()) {
161 if (d_queryValidationState != Indeterminate) {
162 g_stats.dnssecValidations++;
163 }
164 increaseDNSSECStateCounter(d_queryValidationState);
165 }
166
167 return res;
168 }
169
170 /*! Handles all special, built-in names
171 * Fills ret with an answer and returns true if it handled the query.
172 *
173 * Handles the following queries (and their ANY variants):
174 *
175 * - localhost. IN A
176 * - localhost. IN AAAA
177 * - 1.0.0.127.in-addr.arpa. IN PTR
178 * - 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
179 * - version.bind. CH TXT
180 * - version.pdns. CH TXT
181 * - id.server. CH TXT
182 * - trustanchor.server CH TXT
183 * - negativetrustanchor.server CH TXT
184 */
185 bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret)
186 {
187 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."),
188 localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns."), trustanchorserver("trustanchor.server."),
189 negativetrustanchorserver("negativetrustanchor.server.");
190
191 bool handled = false;
192 vector<pair<QType::typeenum, string> > answers;
193
194 if ((qname == arpa || qname == ip6_arpa) &&
195 qclass == QClass::IN) {
196 handled = true;
197 if (qtype == QType::PTR || qtype == QType::ANY)
198 answers.push_back({QType::PTR, "localhost."});
199 }
200
201 if (qname == localhost &&
202 qclass == QClass::IN) {
203 handled = true;
204 if (qtype == QType::A || qtype == QType::ANY)
205 answers.push_back({QType::A, "127.0.0.1"});
206 if (qtype == QType::AAAA || qtype == QType::ANY)
207 answers.push_back({QType::AAAA, "::1"});
208 }
209
210 if ((qname == versionbind || qname == idserver || qname == versionpdns) &&
211 qclass == QClass::CHAOS) {
212 handled = true;
213 if (qtype == QType::TXT || qtype == QType::ANY) {
214 if(qname == versionbind || qname == versionpdns)
215 answers.push_back({QType::TXT, "\""+::arg()["version-string"]+"\""});
216 else if (s_serverID != "disabled")
217 answers.push_back({QType::TXT, "\""+s_serverID+"\""});
218 }
219 }
220
221 if (qname == trustanchorserver && qclass == QClass::CHAOS &&
222 ::arg().mustDo("allow-trust-anchor-query")) {
223 handled = true;
224 if (qtype == QType::TXT || qtype == QType::ANY) {
225 auto luaLocal = g_luaconfs.getLocal();
226 for (auto const &dsAnchor : luaLocal->dsAnchors) {
227 ostringstream ans;
228 ans<<"\"";
229 ans<<dsAnchor.first.toString(); // Explicit toString to have a trailing dot
230 for (auto const &dsRecord : dsAnchor.second) {
231 ans<<" ";
232 ans<<dsRecord.d_tag;
233 }
234 ans << "\"";
235 answers.push_back({QType::TXT, ans.str()});
236 }
237 }
238 }
239
240 if (qname == negativetrustanchorserver && qclass == QClass::CHAOS &&
241 ::arg().mustDo("allow-trust-anchor-query")) {
242 handled = true;
243 if (qtype == QType::TXT || qtype == QType::ANY) {
244 auto luaLocal = g_luaconfs.getLocal();
245 for (auto const &negAnchor : luaLocal->negAnchors) {
246 ostringstream ans;
247 ans<<"\"";
248 ans<<negAnchor.first.toString(); // Explicit toString to have a trailing dot
249 if (negAnchor.second.length())
250 ans<<" "<<negAnchor.second;
251 ans << "\"";
252 answers.push_back({QType::TXT, ans.str()});
253 }
254 }
255 }
256
257 if (handled && !answers.empty()) {
258 ret.clear();
259 d_wasOutOfBand=true;
260
261 DNSRecord dr;
262 dr.d_name = qname;
263 dr.d_place = DNSResourceRecord::ANSWER;
264 dr.d_class = qclass;
265 dr.d_ttl = 86400;
266 for (const auto& ans : answers) {
267 dr.d_type = ans.first;
268 dr.d_content = DNSRecordContent::mastermake(ans.first, qclass, ans.second);
269 ret.push_back(dr);
270 }
271 }
272
273 return handled;
274 }
275
276
277 //! This is the 'out of band resolver', in other words, the authoritative server
278 void SyncRes::AuthDomain::addSOA(std::vector<DNSRecord>& records) const
279 {
280 SyncRes::AuthDomain::records_t::const_iterator ziter = d_records.find(boost::make_tuple(getName(), QType::SOA));
281 if (ziter != d_records.end()) {
282 DNSRecord dr = *ziter;
283 dr.d_place = DNSResourceRecord::AUTHORITY;
284 records.push_back(dr);
285 }
286 else {
287 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
288 }
289 }
290
291 int SyncRes::AuthDomain::getRecords(const DNSName& qname, uint16_t qtype, std::vector<DNSRecord>& records) const
292 {
293 int result = RCode::NoError;
294 records.clear();
295
296 // partial lookup
297 std::pair<records_t::const_iterator,records_t::const_iterator> range = d_records.equal_range(tie(qname));
298
299 SyncRes::AuthDomain::records_t::const_iterator ziter;
300 bool somedata = false;
301
302 for(ziter = range.first; ziter != range.second; ++ziter) {
303 somedata = true;
304
305 if(qtype == QType::ANY || ziter->d_type == qtype || ziter->d_type == QType::CNAME) {
306 // let rest of nameserver do the legwork on this one
307 records.push_back(*ziter);
308 }
309 else if (ziter->d_type == QType::NS && ziter->d_name.countLabels() > getName().countLabels()) {
310 // we hit a delegation point!
311 DNSRecord dr = *ziter;
312 dr.d_place=DNSResourceRecord::AUTHORITY;
313 records.push_back(dr);
314 }
315 }
316
317 if (!records.empty()) {
318 /* We have found an exact match, we're done */
319 // cerr<<qname<<": exact match in zone '"<<getName()<<"'"<<endl;
320 return result;
321 }
322
323 if (somedata) {
324 /* We have records for that name, but not of the wanted qtype */
325 // cerr<<qname<<": found record in '"<<getName()<<"', but nothing of the right type, sending SOA"<<endl;
326 addSOA(records);
327
328 return result;
329 }
330
331 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
332 DNSName wcarddomain(qname);
333 while(wcarddomain != getName() && wcarddomain.chopOff()) {
334 // cerr<<qname<<": trying '*."<<wcarddomain<<"' in "<<getName()<<endl;
335 range = d_records.equal_range(boost::make_tuple(g_wildcarddnsname + wcarddomain));
336 if (range.first==range.second)
337 continue;
338
339 for(ziter = range.first; ziter != range.second; ++ziter) {
340 DNSRecord dr = *ziter;
341 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
342 if(dr.d_type == qtype || qtype == QType::ANY || dr.d_type == QType::CNAME) {
343 dr.d_name = qname;
344 dr.d_place = DNSResourceRecord::ANSWER;
345 records.push_back(dr);
346 }
347 }
348
349 if (records.empty()) {
350 addSOA(records);
351 }
352
353 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
354 return result;
355 }
356
357 /* Nothing for this name, no wildcard, let's see if there is some NS */
358 DNSName nsdomain(qname);
359 while (nsdomain.chopOff() && nsdomain != getName()) {
360 range = d_records.equal_range(boost::make_tuple(nsdomain,QType::NS));
361 if(range.first == range.second)
362 continue;
363
364 for(ziter = range.first; ziter != range.second; ++ziter) {
365 DNSRecord dr = *ziter;
366 dr.d_place = DNSResourceRecord::AUTHORITY;
367 records.push_back(dr);
368 }
369 }
370
371 if(records.empty()) {
372 // cerr<<qname<<": no NS match in zone '"<<getName()<<"' either, handing out SOA"<<endl;
373 addSOA(records);
374 result = RCode::NXDomain;
375 }
376
377 return result;
378 }
379
380 bool SyncRes::doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res)
381 {
382 d_authzonequeries++;
383 s_authzonequeries++;
384
385 res = domain.getRecords(qname, qtype.getCode(), ret);
386 return true;
387 }
388
389 bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int& res)
390 {
391 string prefix;
392 if(doLog()) {
393 prefix=d_prefix;
394 prefix.append(depth, ' ');
395 }
396
397 DNSName authdomain(qname);
398 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
399 if(iter==t_sstorage.domainmap->end() || !iter->second.isAuth()) {
400 LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
401 return false;
402 }
403
404 LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
405 return doOOBResolve(iter->second, qname, qtype, ret, res);
406 }
407
408 bool SyncRes::isForwardOrAuth(const DNSName &qname) const {
409 DNSName authname(qname);
410 domainmap_t::const_iterator iter = getBestAuthZone(&authname);
411 return iter != t_sstorage.domainmap->end();
412 }
413
414 uint64_t SyncRes::doEDNSDump(int fd)
415 {
416 int newfd = dup(fd);
417 if (newfd == -1) {
418 return 0;
419 }
420 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
421 if (!fp) {
422 close(newfd);
423 return 0;
424 }
425 uint64_t count = 0;
426
427 fprintf(fp.get(),"; edns from thread follows\n;\n");
428 for(const auto& eds : t_sstorage.ednsstatus) {
429 count++;
430 char tmp[26];
431 fprintf(fp.get(), "%s\t%d\t%s", eds.address.toString().c_str(), (int)eds.mode, ctime_r(&eds.modeSetAt, tmp));
432 }
433 return count;
434 }
435
436 uint64_t SyncRes::doDumpNSSpeeds(int fd)
437 {
438 int newfd = dup(fd);
439 if (newfd == -1) {
440 return 0;
441 }
442 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
443 if (!fp) {
444 close(newfd);
445 return 0;
446 }
447 fprintf(fp.get(), "; nsspeed dump from thread follows\n;\n");
448 uint64_t count=0;
449
450 for(const auto& i : t_sstorage.nsSpeeds)
451 {
452 count++;
453
454 // an <empty> can appear hear in case of authoritative (hosted) zones
455 fprintf(fp.get(), "%s -> ", i.first.toLogString().c_str());
456 for(const auto& j : i.second.d_collection)
457 {
458 // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
459 fprintf(fp.get(), "%s/%f ", j.first.toString().c_str(), j.second.peek());
460 }
461 fprintf(fp.get(), "\n");
462 }
463 return count;
464 }
465
466 uint64_t SyncRes::doDumpThrottleMap(int fd)
467 {
468 int newfd = dup(fd);
469 if (newfd == -1) {
470 return 0;
471 }
472 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
473 if (!fp) {
474 close(newfd);
475 return 0;
476 }
477 fprintf(fp.get(), "; throttle map dump follows\n");
478 fprintf(fp.get(), "; remote IP\tqname\tqtype\tcount\tttd\n");
479 uint64_t count=0;
480
481 const auto& throttleMap = t_sstorage.throttle.getThrottleMap();
482 for(const auto i : throttleMap)
483 {
484 count++;
485 char tmp[26];
486 // remote IP, dns name, qtype, count, ttd
487 fprintf(fp.get(), "%s\t%s\t%d\t%u\t%s", i.thing.get<0>().toString().c_str(), i.thing.get<1>().toLogString().c_str(), i.thing.get<2>(), i.count, ctime_r(&i.ttd, tmp));
488 }
489
490 return count;
491 }
492
493 uint64_t SyncRes::doDumpFailedServers(int fd)
494 {
495 int newfd = dup(fd);
496 if (newfd == -1) {
497 return 0;
498 }
499 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(newfd, "w"), fclose);
500 if (!fp) {
501 close(newfd);
502 return 0;
503 }
504 fprintf(fp.get(), "; failed servers dump follows\n");
505 fprintf(fp.get(), "; remote IP\tcount\ttimestamp\n");
506 uint64_t count=0;
507
508 for(const auto& i : t_sstorage.fails.getMap())
509 {
510 count++;
511 char tmp[26];
512 ctime_r(&i.last, tmp);
513 fprintf(fp.get(), "%s\t%lld\t%s", i.address.toString().c_str(),
514 static_cast<long long>(i.value), tmp);
515 }
516
517 return count;
518 }
519
520 /* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide
521 to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records
522 so that if there are RRSIGs for a name, we'll have them.
523
524 However, some hosts simply can't answer questions which ask for DNSSEC. This can manifest itself as:
525 * No answer
526 * FormErr
527 * Nonsense answer
528
529 The cause of "No answer" may be fragmentation, and it is tempting to probe if smaller answers would get through.
530 Another cause of "No answer" may simply be a network condition.
531 Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
532
533 Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
534 A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
535 clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
536 elsewhere. It may not have happened yet.
537
538 For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
539 */
540
541 int 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
542 {
543 /* what is your QUEST?
544 the goal is to get as many remotes as possible on the highest level of EDNS support
545 The levels are:
546
547 0) UNKNOWN Unknown state
548 1) EDNS: Honors EDNS0
549 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
550 3) NOEDNS: Generates FORMERR on EDNS queries
551
552 Everybody starts out assumed to be '0'.
553 If '0', send out EDNS0
554 If you FORMERR us, go to '3',
555 If no EDNS in response, go to '2'
556 If '1', send out EDNS0
557 If FORMERR, downgrade to 3
558 If '2', keep on including EDNS0, see what happens
559 Same behaviour as 0
560 If '3', send bare queries
561 */
562
563 auto ednsstatus = t_sstorage.ednsstatus.insert(ip).first; // does this include port? YES
564 auto &ind = t_sstorage.ednsstatus.get<ComboAddress>();
565 if (ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
566 t_sstorage.ednsstatus.reset(ind, ednsstatus);
567 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
568 }
569
570 const SyncRes::EDNSStatus::EDNSMode *mode = &ednsstatus->mode;
571 const SyncRes::EDNSStatus::EDNSMode oldmode = *mode;
572 int EDNSLevel = 0;
573 auto luaconfsLocal = g_luaconfs.getLocal();
574 ResolveContext ctx;
575 #ifdef HAVE_PROTOBUF
576 ctx.d_initialRequestId = d_initialRequestId;
577 #endif
578 #ifdef HAVE_FSTRM
579 ctx.d_auth = auth;
580 #endif
581
582 int ret;
583 for(int tries = 0; tries < 3; ++tries) {
584 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
585
586 if (*mode == EDNSStatus::NOEDNS) {
587 g_stats.noEdnsOutQueries++;
588 EDNSLevel = 0; // level != mode
589 }
590 else if (ednsMANDATORY || *mode == EDNSStatus::UNKNOWN || *mode == EDNSStatus::EDNSOK || *mode == EDNSStatus::EDNSIGNORANT)
591 EDNSLevel = 1;
592
593 DNSName sendQname(domain);
594 if (g_lowercaseOutgoing)
595 sendQname.makeUsLowerCase();
596
597 if (d_asyncResolve) {
598 ret = d_asyncResolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, res, chained);
599 }
600 else {
601 ret=asyncresolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, d_outgoingProtobufServers, d_frameStreamServers, luaconfsLocal->outgoingProtobufExportConfig.exportTypes, res, chained);
602 }
603 // ednsstatus might be cleared, so do a new lookup
604 ednsstatus = t_sstorage.ednsstatus.insert(ip).first;
605 mode = &ednsstatus->mode;
606 if(ret < 0) {
607 return ret; // transport error, nothing to learn here
608 }
609
610 if(ret == 0) { // timeout, not doing anything with it now
611 return ret;
612 }
613 else if (*mode == EDNSStatus::UNKNOWN || *mode == EDNSStatus::EDNSOK || *mode == EDNSStatus::EDNSIGNORANT ) {
614 if(res->d_validpacket && !res->d_haveEDNS && res->d_rcode == RCode::FormErr) {
615 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
616 t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::NOEDNS);
617 continue;
618 }
619 else if(!res->d_haveEDNS) {
620 if (*mode != EDNSStatus::EDNSIGNORANT) {
621 t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSIGNORANT);
622 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 2"<<endl;
623 }
624 }
625 else {
626 t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSOK);
627 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
628 }
629
630 }
631 if (oldmode != *mode || !ednsstatus->modeSetAt)
632 t_sstorage.ednsstatus.setTS(ind, ednsstatus, d_now.tv_sec);
633 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
634 return ret;
635 }
636 return ret;
637 }
638
639 #define QLOG(x) LOG(prefix << " child=" << child << ": " << x << endl)
640
641 int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state) {
642
643 if (!getQNameMinimization() || isForwardOrAuth(qname)) {
644 return doResolveNoQNameMinimization(qname, qtype, ret, depth, beenthere, state);
645 }
646
647 // The qname minimization algorithm is a simplified version of the one in RFC 7816 (bis).
648 // It could be simplified because the cache maintenance (both positive and negative)
649 // is already done by doResolveNoQNameMinimization().
650 //
651 // Sketch of algorithm:
652 // Check cache
653 // If result found: done
654 // Otherwise determine closes ancestor from cache data
655 // Repeat querying A, adding more labels of the original qname
656 // If we get a delegation continue at ancestor determination
657 // Until we have the full name.
658 //
659 // The algorithm starts with adding a single label per iteration, and
660 // moves to three labels per iteration after three iterations.
661
662 DNSName child;
663 string prefix = d_prefix;
664 prefix.append(depth, ' ');
665 prefix.append(string("QM ") + qname.toString() + "|" + qtype.getName());
666
667 QLOG("doResolve");
668
669 // Look in cache only
670 vector<DNSRecord> retq;
671 bool old = setCacheOnly(true);
672 bool fromCache = false;
673 int res = doResolveNoQNameMinimization(qname, qtype, retq, depth + 1, beenthere, state, &fromCache);
674 setCacheOnly(old);
675 if (fromCache) {
676 QLOG("Step0 Found in cache");
677 ret.insert(ret.end(), retq.begin(), retq.end());
678 return res;
679 }
680 QLOG("Step0 Not cached");
681
682 const unsigned int qnamelen = qname.countLabels();
683
684 for (unsigned int i = 0; i <= qnamelen; ) {
685
686 // Step 1
687 vector<DNSRecord> bestns;
688 DNSName nsdomain(qname);
689 if (qtype == QType::DS) {
690 nsdomain.chopOff();
691 }
692 // the two retries allow getBestNSFromCache&co to reprime the root
693 // hints, in case they ever go missing
694 for (int tries = 0; tries < 2 && bestns.empty(); ++tries) {
695 bool flawedNSSet = false;
696 set<GetBestNSAnswer> beenthereIgnored;
697 getBestNSFromCache(nsdomain, qtype, bestns, &flawedNSSet, depth + 1, beenthereIgnored);
698 }
699
700 if (bestns.size() == 0) {
701 // Something terrible is wrong
702 QLOG("Step1 No ancestor found return ServFail");
703 return RCode::ServFail;
704 }
705
706 const DNSName& ancestor(bestns[0].d_name);
707 QLOG("Step1 Ancestor from cache is " << ancestor.toString());
708 child = ancestor;
709
710 unsigned int targetlen = std::min(child.countLabels() + (i > 3 ? 3 : 1), qnamelen);
711
712 for (; i <= qnamelen; i++) {
713 // Step 2
714 while (child.countLabels() < targetlen) {
715 child.prependRawLabel(qname.getRawLabel(qnamelen - child.countLabels() - 1));
716 }
717 targetlen += i > 3 ? 3 : 1;
718 targetlen = std::min(targetlen, qnamelen);
719
720 QLOG("Step2 New child");
721
722 // Step 3 resolve
723 if (child == qname) {
724 QLOG("Step3 Going to do final resolve");
725 res = doResolveNoQNameMinimization(qname, qtype, ret, depth + 1, beenthere, state);
726 QLOG("Step3 Final resolve: " << RCode::to_s(res) << "/" << ret.size());
727 return res;
728 }
729
730 // Step 4
731 QLOG("Step4 Resolve A for child");
732 retq.resize(0);
733 StopAtDelegation stopAtDelegation = Stop;
734 res = doResolveNoQNameMinimization(child, QType::A, retq, depth + 1, beenthere, state, NULL, &stopAtDelegation);
735 QLOG("Step4 Resolve A result is " << RCode::to_s(res) << "/" << retq.size() << "/" << stopAtDelegation);
736 if (stopAtDelegation == Stopped) {
737 QLOG("Delegation seen, continue at step 1");
738 break;
739 }
740
741 if (res != RCode::NoError) {
742 // Case 5: unexpected answer
743 QLOG("Step5: other rcode, last effort final resolve");
744 setQNameMinimization(false);
745 res = doResolveNoQNameMinimization(qname, qtype, ret, depth + 1, beenthere, state);
746
747 if(res == RCode::NoError) {
748 s_qnameminfallbacksuccess++;
749 }
750
751 QLOG("Step5 End resolve: " << RCode::to_s(res) << "/" << ret.size());
752 return res;
753 }
754 }
755 }
756
757 // Should not be reached
758 QLOG("Max iterations reached, return ServFail");
759 return RCode::ServFail;
760 }
761
762 /*! This function will check the cache and go out to the internet if the answer is not in cache
763 *
764 * \param qname The name we need an answer for
765 * \param qtype
766 * \param ret The vector of DNSRecords we need to fill with the answers
767 * \param depth The recursion depth we are in
768 * \param beenthere
769 * \param fromCache tells the caller the result came from the cache, may be nullptr
770 * \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
771 * \return DNS RCODE or -1 (Error)
772 */
773 int SyncRes::doResolveNoQNameMinimization(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state, bool *fromCache, StopAtDelegation *stopAtDelegation)
774 {
775 string prefix;
776 if(doLog()) {
777 prefix=d_prefix;
778 prefix.append(depth, ' ');
779 }
780
781 LOG(prefix<<qname<<": Wants "<< (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing, "<<(d_requireAuthData ? "" : "NO ")<<"auth data in query for "<<qtype.getName()<<endl);
782
783 state = Indeterminate;
784
785 if(s_maxdepth && depth > s_maxdepth)
786 throw ImmediateServFailException("More than "+std::to_string(s_maxdepth)+" (max-recursion-depth) levels of recursion needed while resolving "+qname.toLogString());
787
788 int res=0;
789
790 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
791 if(!(d_updatingRootNS && qtype.getCode()==QType::NS && qname.isRoot())) {
792 if(d_cacheonly) { // very limited OOB support
793 LWResult lwr;
794 LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
795 DNSName authname(qname);
796 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
797 if(iter != t_sstorage.domainmap->end()) {
798 if(iter->second.isAuth()) {
799 ret.clear();
800 d_wasOutOfBand = doOOBResolve(qname, qtype, ret, depth, res);
801 if (fromCache)
802 *fromCache = d_wasOutOfBand;
803 return res;
804 }
805 else {
806 const vector<ComboAddress>& servers = iter->second.d_servers;
807 const ComboAddress remoteIP = servers.front();
808 LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
809
810 boost::optional<Netmask> nm;
811 bool chained = false;
812 res=asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, authname, qtype.getCode(), false, false, &d_now, nm, &lwr, &chained);
813
814 d_totUsec += lwr.d_usec;
815 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
816 if (fromCache)
817 *fromCache = true;
818
819 // filter out the good stuff from lwr.result()
820 if (res == 1) {
821 for(const auto& rec : lwr.d_records) {
822 if(rec.d_place == DNSResourceRecord::ANSWER)
823 ret.push_back(rec);
824 }
825 return 0;
826 }
827 else {
828 return RCode::ServFail;
829 }
830 }
831 }
832 }
833
834 DNSName authname(qname);
835 bool wasForwardedOrAuthZone = false;
836 bool wasAuthZone = false;
837 bool wasForwardRecurse = false;
838 domainmap_t::const_iterator iter = getBestAuthZone(&authname);
839 if(iter != t_sstorage.domainmap->end()) {
840 const auto& domain = iter->second;
841 wasForwardedOrAuthZone = true;
842
843 if (domain.isAuth()) {
844 wasAuthZone = true;
845 } else if (domain.shouldRecurse()) {
846 wasForwardRecurse = true;
847 }
848 }
849
850 if(!d_skipCNAMECheck && doCNAMECacheCheck(qname, qtype, ret, depth, res, state, wasAuthZone, wasForwardRecurse)) { // will reroute us if needed
851 d_wasOutOfBand = wasAuthZone;
852 return res;
853 }
854
855 if(doCacheCheck(qname, authname, wasForwardedOrAuthZone, wasAuthZone, wasForwardRecurse, qtype, ret, depth, res, state)) {
856 // we done
857 d_wasOutOfBand = wasAuthZone;
858 if (fromCache)
859 *fromCache = true;
860 return res;
861 }
862 }
863
864 if(d_cacheonly)
865 return 0;
866
867 LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
868
869 DNSName subdomain(qname);
870 if(qtype == QType::DS) subdomain.chopOff();
871
872 NsSet nsset;
873 bool flawedNSSet=false;
874
875 /* we use subdomain here instead of qname because for DS queries we only care about the state of the parent zone */
876 computeZoneCuts(subdomain, g_rootdnsname, depth);
877
878 // the two retries allow getBestNSNamesFromCache&co to reprime the root
879 // hints, in case they ever go missing
880 for(int tries=0;tries<2 && nsset.empty();++tries) {
881 subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
882 }
883
884 state = getValidationStatus(qname, false);
885
886 LOG(prefix<<qname<<": initial validation status for "<<qname<<" is "<<vStates[state]<<endl);
887
888 if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state, stopAtDelegation)))
889 return 0;
890
891 LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
892
893 return res<0 ? RCode::ServFail : res;
894 }
895
896 #if 0
897 // for testing purposes
898 static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
899 {
900 return !(a.sin4.sin_family < a.sin4.sin_family);
901 }
902 #endif
903
904 struct speedOrderCA
905 {
906 speedOrderCA(std::map<ComboAddress,float>& speeds): d_speeds(speeds) {}
907 bool operator()(const ComboAddress& a, const ComboAddress& b) const
908 {
909 return d_speeds[a] < d_speeds[b];
910 }
911 std::map<ComboAddress, float>& d_speeds;
912 };
913
914 /** This function explicitly goes out for A or AAAA addresses
915 */
916 vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere, bool cacheOnly)
917 {
918 typedef vector<DNSRecord> res_t;
919 typedef vector<ComboAddress> ret_t;
920 ret_t ret;
921
922 bool oldCacheOnly = setCacheOnly(cacheOnly);
923 bool oldRequireAuthData = d_requireAuthData;
924 bool oldValidationRequested = d_DNSSECValidationRequested;
925 d_requireAuthData = false;
926 d_DNSSECValidationRequested = false;
927
928 try {
929 vState newState = Indeterminate;
930 res_t resv4;
931 // If IPv4 ever becomes second class, we should revisit this
932 if (doResolve(qname, QType::A, resv4, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out
933 for (auto const &i : resv4) {
934 if (i.d_type == QType::A) {
935 if (auto rec = getRR<ARecordContent>(i)) {
936 ret.push_back(rec->getCA(53));
937 }
938 }
939 }
940 }
941 if (s_doIPv6) {
942 if (ret.empty()) {
943 // We did not find IPv4 addresses, try to get IPv6 ones
944 newState = Indeterminate;
945 res_t resv6;
946 if (doResolve(qname, QType::AAAA, resv6, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out
947 for (const auto &i : resv6) {
948 if (i.d_type == QType::AAAA) {
949 if (auto rec = getRR<AAAARecordContent>(i))
950 ret.push_back(rec->getCA(53));
951 }
952 }
953 }
954 }
955 } else {
956 // We have some IPv4 records, don't bother with going out to get IPv6, but do consult the cache
957 // Once IPv6 adoption matters, this needs to be revisited
958 res_t cset;
959 if (s_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), false, &cset, d_cacheRemote) > 0) {
960 for (const auto &i : cset) {
961 if (i.d_ttl > (unsigned int)d_now.tv_sec ) {
962 if (auto rec = getRR<AAAARecordContent>(i)) {
963 ret.push_back(rec->getCA(53));
964 }
965 }
966 }
967 }
968 }
969 }
970 catch (const PolicyHitException& e) {
971 /* we ignore a policy hit while trying to retrieve the addresses
972 of a NS and keep processing the current query */
973 }
974
975 d_requireAuthData = oldRequireAuthData;
976 d_DNSSECValidationRequested = oldValidationRequested;
977 setCacheOnly(oldCacheOnly);
978
979 /* we need to remove from the nsSpeeds collection the existing IPs
980 for this nameserver that are no longer in the set, even if there
981 is only one or none at all in the current set.
982 */
983 map<ComboAddress, float> speeds;
984 auto& collection = t_sstorage.nsSpeeds[qname];
985 float factor = collection.getFactor(d_now);
986 for(const auto& val: ret) {
987 speeds[val] = collection.d_collection[val].get(factor);
988 }
989
990 t_sstorage.nsSpeeds[qname].purge(speeds);
991
992 if(ret.size() > 1) {
993 random_shuffle(ret.begin(), ret.end());
994 speedOrderCA so(speeds);
995 stable_sort(ret.begin(), ret.end(), so);
996
997 if(doLog()) {
998 string prefix=d_prefix;
999 prefix.append(depth, ' ');
1000 LOG(prefix<<"Nameserver "<<qname<<" IPs: ");
1001 bool first = true;
1002 for(const auto& addr : ret) {
1003 if (first) {
1004 first = false;
1005 }
1006 else {
1007 LOG(", ");
1008 }
1009 LOG((addr.toString())<<"(" << (boost::format("%0.2f") % (speeds[addr]/1000.0)).str() <<"ms)");
1010 }
1011 LOG(endl);
1012 }
1013 }
1014
1015 return ret;
1016 }
1017
1018 void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere)
1019 {
1020 string prefix;
1021 DNSName subdomain(qname);
1022 if(doLog()) {
1023 prefix=d_prefix;
1024 prefix.append(depth, ' ');
1025 }
1026 bestns.clear();
1027 bool brokeloop;
1028 do {
1029 brokeloop=false;
1030 LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
1031 vector<DNSRecord> ns;
1032 *flawedNSSet = false;
1033
1034 if(s_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), false, &ns, d_cacheRemote) > 0) {
1035 bestns.reserve(ns.size());
1036
1037 for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
1038 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
1039 vector<DNSRecord> aset;
1040
1041 const DNSRecord& dr=*k;
1042 auto nrr = getRR<NSRecordContent>(dr);
1043 if(nrr && (!nrr->getNS().isPartOf(subdomain) || s_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
1044 false, doLog() ? &aset : 0, d_cacheRemote) > 5)) {
1045 bestns.push_back(dr);
1046 LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<nrr->getNS()<<"'"<<endl);
1047 LOG(prefix<<qname<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
1048 if(!aset.empty()) {
1049 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
1050 }
1051 else {
1052 LOG(", not in cache / did not look at cache"<<endl);
1053 }
1054 }
1055 else {
1056 *flawedNSSet=true;
1057 LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
1058 }
1059 }
1060 }
1061
1062 if(!bestns.empty()) {
1063 GetBestNSAnswer answer;
1064 answer.qname=qname;
1065 answer.qtype=qtype.getCode();
1066 for(const auto& dr : bestns) {
1067 if (auto nsContent = getRR<NSRecordContent>(dr)) {
1068 answer.bestns.insert(make_pair(dr.d_name, nsContent->getNS()));
1069 }
1070 }
1071
1072 auto insertionPair = beenthere.insert(std::move(answer));
1073 if(!insertionPair.second) {
1074 brokeloop=true;
1075 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
1076 ;
1077 if(doLog())
1078 for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
1079 bool neo = (j == insertionPair.first);
1080 LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
1081 }
1082 bestns.clear();
1083 }
1084 else {
1085 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
1086 return;
1087 }
1088 }
1089 }
1090 LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
1091
1092 if(subdomain.isRoot() && !brokeloop) {
1093 // We lost the root NS records
1094 primeHints();
1095 primeRootNSZones(g_dnssecmode != DNSSECMode::Off);
1096 LOG(prefix<<qname<<": reprimed the root"<<endl);
1097 /* let's prevent an infinite loop */
1098 if (!d_updatingRootNS) {
1099 getRootNS(d_now, d_asyncResolve);
1100 }
1101 }
1102 } while(subdomain.chopOff());
1103 }
1104
1105 SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) const
1106 {
1107 if (t_sstorage.domainmap->empty()) {
1108 return t_sstorage.domainmap->end();
1109 }
1110
1111 SyncRes::domainmap_t::const_iterator ret;
1112 do {
1113 ret=t_sstorage.domainmap->find(*qname);
1114 if(ret!=t_sstorage.domainmap->end())
1115 break;
1116 }while(qname->chopOff());
1117 return ret;
1118 }
1119
1120 /** doesn't actually do the work, leaves that to getBestNSFromCache */
1121 DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere)
1122 {
1123 DNSName authdomain(qname);
1124
1125 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
1126 if(iter!=t_sstorage.domainmap->end()) {
1127 if( iter->second.isAuth() )
1128 // this gets picked up in doResolveAt, the empty DNSName, combined with the
1129 // empty vector means 'we are auth for this zone'
1130 nsset.insert({DNSName(), {{}, false}});
1131 else {
1132 // Again, picked up in doResolveAt. An empty DNSName, combined with a
1133 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
1134 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
1135 nsset.insert({DNSName(), {iter->second.d_servers, iter->second.shouldRecurse() }});
1136 }
1137 return authdomain;
1138 }
1139
1140 DNSName subdomain(qname);
1141 vector<DNSRecord> bestns;
1142 getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
1143
1144 for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) {
1145 // The actual resolver code will not even look at the ComboAddress or bool
1146 const auto nsContent = getRR<NSRecordContent>(*k);
1147 if (nsContent) {
1148 nsset.insert({nsContent->getNS(), {{}, false}});
1149 if(k==bestns.cbegin())
1150 subdomain=k->d_name;
1151 }
1152 }
1153 return subdomain;
1154 }
1155
1156 void SyncRes::updateValidationStatusInCache(const DNSName &qname, const QType& qt, bool aa, vState newState) const
1157 {
1158 if (newState == Bogus) {
1159 s_RC->updateValidationStatus(d_now.tv_sec, qname, qt, d_cacheRemote, aa, newState, s_maxbogusttl + d_now.tv_sec);
1160 }
1161 else {
1162 s_RC->updateValidationStatus(d_now.tv_sec, qname, qt, d_cacheRemote, aa, newState, boost::none);
1163 }
1164 }
1165
1166 bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res, vState& state, bool wasAuthZone, bool wasForwardRecurse)
1167 {
1168 string prefix;
1169 if(doLog()) {
1170 prefix=d_prefix;
1171 prefix.append(depth, ' ');
1172 }
1173
1174 if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
1175 LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
1176 res=RCode::ServFail;
1177 return true;
1178 }
1179
1180 vector<DNSRecord> cset;
1181 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
1182 vector<std::shared_ptr<DNSRecord>> authorityRecs;
1183 bool wasAuth;
1184 uint32_t capTTL = std::numeric_limits<uint32_t>::max();
1185 DNSName foundName;
1186 QType foundQT = QType(0); // 0 == QTYPE::ENT
1187
1188 LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<qname<<"|CNAME"<<"'"<<endl);
1189 /* we don't require auth data for forward-recurse lookups */
1190 if (s_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth) > 0) {
1191 foundName = qname;
1192 foundQT = QType(QType::CNAME);
1193 }
1194
1195 if (foundName.empty() && qname != g_rootdnsname) {
1196 // look for a DNAME cache hit
1197 auto labels = qname.getRawLabels();
1198 DNSName dnameName(g_rootdnsname);
1199
1200 LOG(prefix<<qname<<": Looking for DNAME cache hit of '"<<qname<<"|DNAME' or its ancestors"<<endl);
1201 do {
1202 dnameName.prependRawLabel(labels.back());
1203 labels.pop_back();
1204 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
1205 break;
1206 }
1207 if (s_RC->get(d_now.tv_sec, dnameName, QType(QType::DNAME), !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth) > 0) {
1208 foundName = dnameName;
1209 foundQT = QType(QType::DNAME);
1210 break;
1211 }
1212 } while(!labels.empty());
1213 }
1214
1215 if (foundName.empty()) {
1216 LOG(prefix<<qname<<": No CNAME or DNAME cache hit of '"<< qname <<"' found"<<endl);
1217 return false;
1218 }
1219
1220 for(auto const &record : cset) {
1221 if (record.d_class != QClass::IN) {
1222 continue;
1223 }
1224
1225 if(record.d_ttl > (unsigned int) d_now.tv_sec) {
1226
1227 if (!wasAuthZone && shouldValidate() && (wasAuth || wasForwardRecurse) && state == Indeterminate && d_requireAuthData) {
1228 /* This means we couldn't figure out the state when this entry was cached,
1229 most likely because we hadn't computed the zone cuts yet. */
1230 /* make sure they are computed before validating */
1231 DNSName subdomain(foundName);
1232 /* if we are retrieving a DS, we only care about the state of the parent zone */
1233 if(qtype == QType::DS)
1234 subdomain.chopOff();
1235
1236 computeZoneCuts(subdomain, g_rootdnsname, depth);
1237
1238 vState recordState = getValidationStatus(foundName, false);
1239 if (recordState == Secure) {
1240 LOG(prefix<<qname<<": got Indeterminate state from the "<<foundQT.getName()<<" cache, validating.."<<endl);
1241 state = SyncRes::validateRecordsWithSigs(depth, foundName, foundQT, foundName, cset, signatures);
1242 if (state != Indeterminate) {
1243 LOG(prefix<<qname<<": got Indeterminate state from the CNAME cache, new validation result is "<<vStates[state]<<endl);
1244 if (state == Bogus) {
1245 capTTL = s_maxbogusttl;
1246 }
1247 updateValidationStatusInCache(foundName, foundQT, wasAuth, state);
1248 }
1249 }
1250 }
1251
1252 LOG(prefix<<qname<<": Found cache "<<foundQT.getName()<<" hit for '"<< foundName << "|"<<foundQT.getName()<<"' to '"<<record.d_content->getZoneRepresentation()<<"', validation state is "<<vStates[state]<<endl);
1253
1254 DNSRecord dr = record;
1255 dr.d_ttl -= d_now.tv_sec;
1256 dr.d_ttl = std::min(dr.d_ttl, capTTL);
1257 const uint32_t ttl = dr.d_ttl;
1258 ret.reserve(ret.size() + 2 + signatures.size() + authorityRecs.size());
1259 ret.push_back(dr);
1260
1261 for(const auto& signature : signatures) {
1262 DNSRecord sigdr;
1263 sigdr.d_type=QType::RRSIG;
1264 sigdr.d_name=foundName;
1265 sigdr.d_ttl=ttl;
1266 sigdr.d_content=signature;
1267 sigdr.d_place=DNSResourceRecord::ANSWER;
1268 sigdr.d_class=QClass::IN;
1269 ret.push_back(sigdr);
1270 }
1271
1272 for(const auto& rec : authorityRecs) {
1273 DNSRecord authDR(*rec);
1274 authDR.d_ttl=ttl;
1275 ret.push_back(authDR);
1276 }
1277
1278 DNSName newTarget;
1279 if (foundQT == QType::DNAME) {
1280 if (qtype == QType::DNAME && qname == foundName) { // client wanted the DNAME, no need to synthesize a CNAME
1281 res = 0;
1282 return true;
1283 }
1284 // Synthesize a CNAME
1285 auto dnameRR = getRR<DNAMERecordContent>(record);
1286 if (dnameRR == nullptr) {
1287 throw ImmediateServFailException("Unable to get record content for "+foundName.toLogString()+"|DNAME cache entry");
1288 }
1289 const auto& dnameSuffix = dnameRR->getTarget();
1290 DNSName targetPrefix = qname.makeRelative(foundName);
1291 try {
1292 dr.d_type = QType::CNAME;
1293 dr.d_name = targetPrefix + foundName;
1294 newTarget = targetPrefix + dnameSuffix;
1295 dr.d_content = std::make_shared<CNAMERecordContent>(CNAMERecordContent(newTarget));
1296 ret.push_back(dr);
1297 } catch (const std::exception &e) {
1298 // We should probably catch an std::range_error here and set the rcode to YXDOMAIN (RFC 6672, section 2.2)
1299 // But this is consistent with processRecords
1300 throw ImmediateServFailException("Unable to perform DNAME substitution(DNAME owner: '" + foundName.toLogString() +
1301 "', DNAME target: '" + dnameSuffix.toLogString() + "', substituted name: '" +
1302 targetPrefix.toLogString() + "." + dnameSuffix.toLogString() +
1303 "' : " + e.what());
1304 }
1305
1306 LOG(prefix<<qname<<": Synthesized "<<dr.d_name<<"|CNAME "<<newTarget<<endl);
1307 }
1308
1309 if(qtype == QType::CNAME) { // perhaps they really wanted a CNAME!
1310 res = 0;
1311 return true;
1312 }
1313
1314 // We have a DNAME _or_ CNAME cache hit and the client wants something else than those two.
1315 // Let's find the answer!
1316 if (foundQT == QType::CNAME) {
1317 const auto cnameContent = getRR<CNAMERecordContent>(record);
1318 if (cnameContent == nullptr) {
1319 throw ImmediateServFailException("Unable to get record content for "+foundName.toLogString()+"|CNAME cache entry");
1320 }
1321 newTarget = cnameContent->getTarget();
1322 }
1323
1324 set<GetBestNSAnswer>beenthere;
1325 vState cnameState = Indeterminate;
1326 res = doResolve(newTarget, qtype, ret, depth+1, beenthere, cnameState);
1327 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the DNAME/CNAME quest: "<<vStates[cnameState]<<endl);
1328 updateValidationState(state, cnameState);
1329
1330 return true;
1331 }
1332 }
1333 throw ImmediateServFailException("Could not determine whether or not there was a CNAME or DNAME in cache for '" + qname.toLogString() + "'");
1334 }
1335
1336 namespace {
1337 struct CacheEntry
1338 {
1339 vector<DNSRecord> records;
1340 vector<shared_ptr<RRSIGRecordContent>> signatures;
1341 uint32_t signaturesTTL{std::numeric_limits<uint32_t>::max()};
1342 };
1343 struct CacheKey
1344 {
1345 DNSName name;
1346 uint16_t type;
1347 DNSResourceRecord::Place place;
1348 bool operator<(const CacheKey& rhs) const {
1349 return tie(type, place, name) < tie(rhs.type, rhs.place, rhs.name);
1350 }
1351 };
1352 typedef map<CacheKey, CacheEntry> tcache_t;
1353 }
1354
1355 static void reapRecordsFromNegCacheEntryForValidation(tcache_t& tcache, const vector<DNSRecord>& records)
1356 {
1357 for (const auto& rec : records) {
1358 if (rec.d_type == QType::RRSIG) {
1359 auto rrsig = getRR<RRSIGRecordContent>(rec);
1360 if (rrsig) {
1361 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
1362 }
1363 } else {
1364 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(rec);
1365 }
1366 }
1367 }
1368
1369 /*!
1370 * Convience function to push the records from records into ret with a new TTL
1371 *
1372 * \param records DNSRecords that need to go into ret
1373 * \param ttl The new TTL for these records
1374 * \param ret The vector of DNSRecords that should contian the records with the modified TTL
1375 */
1376 static void addTTLModifiedRecords(const vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
1377 for (const auto& rec : records) {
1378 DNSRecord r(rec);
1379 r.d_ttl = ttl;
1380 ret.push_back(r);
1381 }
1382 }
1383
1384 void SyncRes::computeNegCacheValidationStatus(const NegCache::NegCacheEntry* ne, const DNSName& qname, const QType& qtype, const int res, vState& state, unsigned int depth)
1385 {
1386 DNSName subdomain(qname);
1387 /* if we are retrieving a DS, we only care about the state of the parent zone */
1388 if(qtype == QType::DS)
1389 subdomain.chopOff();
1390
1391 computeZoneCuts(subdomain, g_rootdnsname, depth);
1392
1393 tcache_t tcache;
1394 reapRecordsFromNegCacheEntryForValidation(tcache, ne->authoritySOA.records);
1395 reapRecordsFromNegCacheEntryForValidation(tcache, ne->authoritySOA.signatures);
1396 reapRecordsFromNegCacheEntryForValidation(tcache, ne->DNSSECRecords.records);
1397 reapRecordsFromNegCacheEntryForValidation(tcache, ne->DNSSECRecords.signatures);
1398
1399 for (const auto& entry : tcache) {
1400 // this happens when we did store signatures, but passed on the records themselves
1401 if (entry.second.records.empty()) {
1402 continue;
1403 }
1404
1405 const DNSName& owner = entry.first.name;
1406
1407 vState recordState = getValidationStatus(owner, false);
1408 if (state == Indeterminate) {
1409 state = recordState;
1410 }
1411
1412 if (recordState == Secure) {
1413 recordState = SyncRes::validateRecordsWithSigs(depth, qname, qtype, owner, entry.second.records, entry.second.signatures);
1414 }
1415
1416 if (recordState != Indeterminate && recordState != state) {
1417 updateValidationState(state, recordState);
1418 if (state != Secure) {
1419 break;
1420 }
1421 }
1422 }
1423
1424 if (state == Secure) {
1425 vState neValidationState = ne->d_validationState;
1426 dState expectedState = res == RCode::NXDomain ? NXDOMAIN : NXQTYPE;
1427 dState denialState = getDenialValidationState(*ne, state, expectedState, false);
1428 updateDenialValidationState(neValidationState, ne->d_name, state, denialState, expectedState, qtype == QType::DS || expectedState == NXDOMAIN);
1429 }
1430 if (state != Indeterminate) {
1431 /* validation succeeded, let's update the cache entry so we don't have to validate again */
1432 boost::optional<uint32_t> capTTD = boost::none;
1433 if (state == Bogus) {
1434 capTTD = d_now.tv_sec + s_maxbogusttl;
1435 }
1436 t_sstorage.negcache.updateValidationStatus(ne->d_name, ne->d_qtype, state, capTTD);
1437 }
1438 }
1439
1440 bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
1441 {
1442 bool giveNegative=false;
1443
1444 string prefix;
1445 if(doLog()) {
1446 prefix=d_prefix;
1447 prefix.append(depth, ' ');
1448 }
1449
1450 // sqname and sqtype are used contain 'higher' names if we have them (e.g. powerdns.com|SOA when we find a negative entry for doesnotexists.powerdns.com|A)
1451 DNSName sqname(qname);
1452 QType sqt(qtype);
1453 uint32_t sttl=0;
1454 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
1455 vState cachedState;
1456 const NegCache::NegCacheEntry* ne = nullptr;
1457
1458 if(s_rootNXTrust &&
1459 t_sstorage.negcache.getRootNXTrust(qname, d_now, &ne) &&
1460 ne->d_auth.isRoot() &&
1461 !(wasForwardedOrAuthZone && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
1462 sttl = ne->d_ttd - d_now.tv_sec;
1463 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne->d_auth<<"' & '"<<ne->d_name<<"' for another "<<sttl<<" seconds"<<endl);
1464 res = RCode::NXDomain;
1465 giveNegative = true;
1466 cachedState = ne->d_validationState;
1467 } else if (t_sstorage.negcache.get(qname, qtype, d_now, &ne)) {
1468 /* If we are looking for a DS, discard NXD if auth == qname
1469 and ask for a specific denial instead */
1470 if (qtype != QType::DS || ne->d_qtype.getCode() || ne->d_auth != qname ||
1471 t_sstorage.negcache.get(qname, qtype, d_now, &ne, true))
1472 {
1473 res = RCode::NXDomain;
1474 sttl = ne->d_ttd - d_now.tv_sec;
1475 giveNegative = true;
1476 cachedState = ne->d_validationState;
1477 if (ne->d_qtype.getCode()) {
1478 LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne->d_auth<<"' for another "<<sttl<<" seconds"<<endl);
1479 res = RCode::NoError;
1480 } else {
1481 LOG(prefix<<qname<<": Entire name '"<<qname<<" is negatively cached via '"<<ne->d_auth<<"' for another "<<sttl<<" seconds"<<endl);
1482 }
1483 }
1484 } else if (s_hardenNXD != HardenNXD::No && !qname.isRoot() && !wasForwardedOrAuthZone) {
1485 auto labels = qname.getRawLabels();
1486 DNSName negCacheName(g_rootdnsname);
1487 negCacheName.prependRawLabel(labels.back());
1488 labels.pop_back();
1489 while(!labels.empty()) {
1490 if (t_sstorage.negcache.get(negCacheName, QType(0), d_now, &ne, true)) {
1491 if (ne->d_validationState == Indeterminate && validationEnabled()) {
1492 // LOG(prefix << negCacheName << " negatively cached and Indeterminate, trying to validate NXDOMAIN" << endl);
1493 // ...
1494 // And get the updated ne struct
1495 //t_sstorage.negcache.get(negCacheName, QType(0), d_now, &ne, true);
1496 }
1497 if ((s_hardenNXD == HardenNXD::Yes && ne->d_validationState != Bogus) || ne->d_validationState == Secure) {
1498 res = RCode::NXDomain;
1499 sttl = ne->d_ttd - d_now.tv_sec;
1500 giveNegative = true;
1501 cachedState = ne->d_validationState;
1502 LOG(prefix<<qname<<": Name '"<<negCacheName<<"' and below, is negatively cached via '"<<ne->d_auth<<"' for another "<<sttl<<" seconds"<<endl);
1503 break;
1504 }
1505 }
1506 negCacheName.prependRawLabel(labels.back());
1507 labels.pop_back();
1508 }
1509 }
1510
1511 if (giveNegative) {
1512
1513 state = cachedState;
1514
1515 if (!wasAuthZone && shouldValidate() && state == Indeterminate) {
1516 LOG(prefix<<qname<<": got Indeterminate state for records retrieved from the negative cache, validating.."<<endl);
1517 computeNegCacheValidationStatus(ne, qname, qtype, res, state, depth);
1518
1519 if (state != cachedState && state == Bogus) {
1520 sttl = std::min(sttl, s_maxbogusttl);
1521 }
1522 }
1523
1524 // Transplant SOA to the returned packet
1525 addTTLModifiedRecords(ne->authoritySOA.records, sttl, ret);
1526 if(d_doDNSSEC) {
1527 addTTLModifiedRecords(ne->authoritySOA.signatures, sttl, ret);
1528 addTTLModifiedRecords(ne->DNSSECRecords.records, sttl, ret);
1529 addTTLModifiedRecords(ne->DNSSECRecords.signatures, sttl, ret);
1530 }
1531
1532 LOG(prefix<<qname<<": updating validation state with negative cache content for "<<qname<<" to "<<vStates[state]<<endl);
1533 return true;
1534 }
1535
1536 vector<DNSRecord> cset;
1537 bool found=false, expired=false;
1538 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
1539 vector<std::shared_ptr<DNSRecord>> authorityRecs;
1540 uint32_t ttl=0;
1541 uint32_t capTTL = std::numeric_limits<uint32_t>::max();
1542 bool wasCachedAuth;
1543 if(s_RC->get(d_now.tv_sec, sqname, sqt, !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth) > 0) {
1544
1545 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
1546
1547 if (!wasAuthZone && shouldValidate() && (wasCachedAuth || wasForwardRecurse) && cachedState == Indeterminate && d_requireAuthData) {
1548
1549 /* This means we couldn't figure out the state when this entry was cached,
1550 most likely because we hadn't computed the zone cuts yet. */
1551 /* make sure they are computed before validating */
1552 DNSName subdomain(sqname);
1553 /* if we are retrieving a DS, we only care about the state of the parent zone */
1554 if(qtype == QType::DS)
1555 subdomain.chopOff();
1556
1557 computeZoneCuts(subdomain, g_rootdnsname, depth);
1558
1559 vState recordState = getValidationStatus(qname, false);
1560 if (recordState == Secure) {
1561 LOG(prefix<<sqname<<": got Indeterminate state from the cache, validating.."<<endl);
1562 cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures);
1563 }
1564 else {
1565 cachedState = recordState;
1566 }
1567
1568 if (cachedState != Indeterminate) {
1569 LOG(prefix<<qname<<": got Indeterminate state from the cache, validation result is "<<vStates[cachedState]<<endl);
1570 if (cachedState == Bogus) {
1571 capTTL = s_maxbogusttl;
1572 }
1573 updateValidationStatusInCache(sqname, sqt, wasCachedAuth, cachedState);
1574 }
1575 }
1576
1577 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
1578
1579 LOG(j->d_content->getZoneRepresentation());
1580
1581 if (j->d_class != QClass::IN) {
1582 continue;
1583 }
1584
1585 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
1586 DNSRecord dr=*j;
1587 dr.d_ttl -= d_now.tv_sec;
1588 dr.d_ttl = std::min(dr.d_ttl, capTTL);
1589 ttl = dr.d_ttl;
1590 ret.push_back(dr);
1591 LOG("[ttl="<<dr.d_ttl<<"] ");
1592 found=true;
1593 }
1594 else {
1595 LOG("[expired] ");
1596 expired=true;
1597 }
1598 }
1599
1600 ret.reserve(ret.size() + signatures.size() + authorityRecs.size());
1601
1602 for(const auto& signature : signatures) {
1603 DNSRecord dr;
1604 dr.d_type=QType::RRSIG;
1605 dr.d_name=sqname;
1606 dr.d_ttl=ttl;
1607 dr.d_content=signature;
1608 dr.d_place = DNSResourceRecord::ANSWER;
1609 dr.d_class=QClass::IN;
1610 ret.push_back(dr);
1611 }
1612
1613 for(const auto& rec : authorityRecs) {
1614 DNSRecord dr(*rec);
1615 dr.d_ttl=ttl;
1616 ret.push_back(dr);
1617 }
1618
1619 LOG(endl);
1620 if(found && !expired) {
1621 if (!giveNegative)
1622 res=0;
1623 LOG(prefix<<qname<<": updating validation state with cache content for "<<qname<<" to "<<vStates[cachedState]<<endl);
1624 state = cachedState;
1625 return true;
1626 }
1627 else
1628 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
1629 }
1630
1631 return false;
1632 }
1633
1634 bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
1635 {
1636 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
1637 }
1638
1639 struct speedOrder
1640 {
1641 bool operator()(const std::pair<DNSName, float> &a, const std::pair<DNSName, float> &b) const
1642 {
1643 return a.second < b.second;
1644 }
1645 };
1646
1647 inline std::vector<std::pair<DNSName, float>> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
1648 {
1649 std::vector<std::pair<DNSName, float>> rnameservers;
1650 rnameservers.reserve(tnameservers.size());
1651 for(const auto& tns: tnameservers) {
1652 float speed = t_sstorage.nsSpeeds[tns.first].get(d_now);
1653 rnameservers.push_back({tns.first, speed});
1654 if(tns.first.empty()) // this was an authoritative OOB zone, don't pollute the nsSpeeds with that
1655 return rnameservers;
1656 }
1657
1658 random_shuffle(rnameservers.begin(),rnameservers.end());
1659 speedOrder so;
1660 stable_sort(rnameservers.begin(),rnameservers.end(), so);
1661
1662 if(doLog()) {
1663 LOG(prefix<<"Nameservers: ");
1664 for(auto i=rnameservers.begin();i!=rnameservers.end();++i) {
1665 if(i!=rnameservers.begin()) {
1666 LOG(", ");
1667 if(!((i-rnameservers.begin())%3)) {
1668 LOG(endl<<prefix<<" ");
1669 }
1670 }
1671 LOG(i->first.toLogString()<<"(" << (boost::format("%0.2f") % (i->second/1000.0)).str() <<"ms)");
1672 }
1673 LOG(endl);
1674 }
1675 return rnameservers;
1676 }
1677
1678 inline vector<ComboAddress> SyncRes::shuffleForwardSpeed(const vector<ComboAddress> &rnameservers, const string &prefix, const bool wasRd)
1679 {
1680 vector<ComboAddress> nameservers = rnameservers;
1681 map<ComboAddress, float> speeds;
1682
1683 for(const auto& val: nameservers) {
1684 float speed;
1685 DNSName nsName = DNSName(val.toStringWithPort());
1686 speed=t_sstorage.nsSpeeds[nsName].get(d_now);
1687 speeds[val]=speed;
1688 }
1689 random_shuffle(nameservers.begin(),nameservers.end());
1690 speedOrderCA so(speeds);
1691 stable_sort(nameservers.begin(),nameservers.end(), so);
1692
1693 if(doLog()) {
1694 LOG(prefix<<"Nameservers: ");
1695 for(vector<ComboAddress>::const_iterator i=nameservers.cbegin();i!=nameservers.cend();++i) {
1696 if(i!=nameservers.cbegin()) {
1697 LOG(", ");
1698 if(!((i-nameservers.cbegin())%3)) {
1699 LOG(endl<<prefix<<" ");
1700 }
1701 }
1702 LOG((wasRd ? string("+") : string("-")) << i->toStringWithPort() <<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
1703 }
1704 LOG(endl);
1705 }
1706 return nameservers;
1707 }
1708
1709 static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<RRSIGRecordContent>& rrsig)
1710 {
1711 uint32_t res = 0;
1712 if (now < rrsig->d_sigexpire) {
1713 res = static_cast<uint32_t>(rrsig->d_sigexpire) - now;
1714 }
1715 return res;
1716 }
1717
1718 static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
1719
1720 /* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1721 *
1722 * \param records The records to parse for the authority SOA and NSEC(3) records
1723 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1724 */
1725 static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne, const time_t now, uint32_t* lowestTTL) {
1726 for(const auto& rec : records) {
1727 if(rec.d_place != DNSResourceRecord::AUTHORITY)
1728 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1729 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1730 // records MUST be in the same section as the records they cover.
1731 // Hence, we ignore all records outside of the AUTHORITY section.
1732 continue;
1733
1734 if(rec.d_type == QType::RRSIG) {
1735 auto rrsig = getRR<RRSIGRecordContent>(rec);
1736 if(rrsig) {
1737 if(rrsig->d_type == QType::SOA) {
1738 ne.authoritySOA.signatures.push_back(rec);
1739 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1740 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1741 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1742 }
1743 }
1744 if(nsecTypes.count(rrsig->d_type)) {
1745 ne.DNSSECRecords.signatures.push_back(rec);
1746 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1747 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1748 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1749 }
1750 }
1751 }
1752 continue;
1753 }
1754 if(rec.d_type == QType::SOA) {
1755 ne.authoritySOA.records.push_back(rec);
1756 if (lowestTTL) {
1757 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1758 }
1759 continue;
1760 }
1761 if(nsecTypes.count(rec.d_type)) {
1762 ne.DNSSECRecords.records.push_back(rec);
1763 if (lowestTTL) {
1764 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1765 }
1766 continue;
1767 }
1768 }
1769 }
1770
1771 static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
1772 {
1773 cspmap_t cspmap;
1774 for(const auto& rec : ne.DNSSECRecords.signatures) {
1775 if(rec.d_type == QType::RRSIG) {
1776 auto rrc = getRR<RRSIGRecordContent>(rec);
1777 if (rrc) {
1778 cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
1779 }
1780 }
1781 }
1782 for(const auto& rec : ne.DNSSECRecords.records) {
1783 cspmap[{rec.d_name, rec.d_type}].records.insert(rec.d_content);
1784 }
1785 return cspmap;
1786 }
1787
1788 // TODO remove after processRecords is fixed!
1789 // Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
1790 static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1791 {
1792 NegCache::NegCacheEntry ne;
1793 harvestNXRecords(records, ne, 0, nullptr);
1794 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
1795 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
1796 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
1797 }
1798
1799 bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
1800 {
1801 /* we skip RPZ processing if:
1802 - it was disabled (d_wantsRPZ is false) ;
1803 - we already got a RPZ hit (d_appliedPolicy.d_type != DNSFilterEngine::PolicyType::None) since
1804 the only way we can get back here is that it was a 'pass-thru' (NoAction) meaning that we should not
1805 process any further RPZ rules.
1806 */
1807 if (d_wantsRPZ && (d_appliedPolicy.d_type == DNSFilterEngine::PolicyType::None || d_appliedPolicy.d_kind == DNSFilterEngine::PolicyKind::NoAction)) {
1808 for (auto const &ns : nameservers) {
1809 bool match = dfe.getProcessingPolicy(ns.first, d_discardedPolicies, d_appliedPolicy);
1810 if (match && d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1811 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1812 return true;
1813 }
1814
1815 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1816 for (auto const &address : ns.second.first) {
1817 match = dfe.getProcessingPolicy(address, d_discardedPolicies, d_appliedPolicy);
1818 if (match && d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1819 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1820 return true;
1821 }
1822 }
1823 }
1824 }
1825 return false;
1826 }
1827
1828 bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
1829 {
1830 /* we skip RPZ processing if:
1831 - it was disabled (d_wantsRPZ is false) ;
1832 - we already got a RPZ hit (d_appliedPolicy.d_type != DNSFilterEngine::PolicyType::None) since
1833 the only way we can get back here is that it was a 'pass-thru' (NoAction) meaning that we should not
1834 process any further RPZ rules.
1835 */
1836 if (d_wantsRPZ && (d_appliedPolicy.d_type == DNSFilterEngine::PolicyType::None || d_appliedPolicy.d_kind == DNSFilterEngine::PolicyKind::NoAction)) {
1837 bool match = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies, d_appliedPolicy);
1838 if (match && d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
1839 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
1840 return true;
1841 }
1842 }
1843 return false;
1844 }
1845
1846 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)
1847 {
1848 vector<ComboAddress> result;
1849
1850 if(!tns->first.empty()) {
1851 LOG(prefix<<qname<<": Trying to resolve NS '"<<tns->first<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
1852 result = getAddrs(tns->first, depth+2, beenthere, cacheOnly);
1853 pierceDontQuery=false;
1854 }
1855 else {
1856 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
1857
1858 if(nameservers[tns->first].first.size() > 1) {
1859 LOG("s");
1860 }
1861 LOG(endl);
1862
1863 sendRDQuery = nameservers[tns->first].second;
1864 result = shuffleForwardSpeed(nameservers[tns->first].first, doLog() ? (prefix+qname.toString()+": ") : string(), sendRDQuery);
1865 pierceDontQuery=true;
1866 }
1867 return result;
1868 }
1869
1870 bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1871 {
1872 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
1873 LOG(prefix<<qname<<": server throttled "<<endl);
1874 s_throttledqueries++; d_throttledqueries++;
1875 return true;
1876 }
1877 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
1878 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
1879 s_throttledqueries++; d_throttledqueries++;
1880 return true;
1881 }
1882 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
1883 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
1884 s_dontqueries++;
1885 return true;
1886 }
1887 return false;
1888 }
1889
1890 bool SyncRes::validationEnabled() const
1891 {
1892 return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
1893 }
1894
1895 uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const
1896 {
1897 uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
1898 for(const auto& record : records)
1899 lowestTTD = min(lowestTTD, record.d_ttl);
1900
1901 /* even if it was not requested for that request (Process, and neither AD nor DO set),
1902 it might be requested at a later time so we need to be careful with the TTL. */
1903 if (validationEnabled() && !signatures.empty()) {
1904 /* if we are validating, we don't want to cache records after their signatures expire. */
1905 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
1906 lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
1907
1908 for(const auto& sig : signatures) {
1909 if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
1910 // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
1911 lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
1912 }
1913 }
1914 }
1915
1916 return lowestTTD;
1917 }
1918
1919 void SyncRes::updateValidationState(vState& state, const vState stateUpdate)
1920 {
1921 LOG(d_prefix<<"validation state was "<<std::string(vStates[state])<<", state update is "<<std::string(vStates[stateUpdate]));
1922
1923 if (stateUpdate == TA) {
1924 state = Secure;
1925 }
1926 else if (stateUpdate == NTA) {
1927 state = Insecure;
1928 }
1929 else if (stateUpdate == Bogus) {
1930 state = Bogus;
1931 }
1932 else if (state == Indeterminate) {
1933 state = stateUpdate;
1934 }
1935 else if (stateUpdate == Insecure) {
1936 if (state != Bogus) {
1937 state = Insecure;
1938 }
1939 }
1940 LOG(", validation state is now "<<std::string(vStates[state])<<endl);
1941 }
1942
1943 vState SyncRes::getTA(const DNSName& zone, dsmap_t& ds)
1944 {
1945 auto luaLocal = g_luaconfs.getLocal();
1946
1947 if (luaLocal->dsAnchors.empty()) {
1948 LOG(d_prefix<<": No trust anchors configured, everything is Insecure"<<endl);
1949 /* We have no TA, everything is insecure */
1950 return Insecure;
1951 }
1952
1953 std::string reason;
1954 if (haveNegativeTrustAnchor(luaLocal->negAnchors, zone, reason)) {
1955 LOG(d_prefix<<": got NTA for '"<<zone<<"'"<<endl);
1956 return NTA;
1957 }
1958
1959 if (getTrustAnchor(luaLocal->dsAnchors, zone, ds)) {
1960 LOG(d_prefix<<": got TA for '"<<zone<<"'"<<endl);
1961 return TA;
1962 }
1963 else {
1964 LOG(d_prefix<<": no TA found for '"<<zone<<"' among "<< luaLocal->dsAnchors.size()<<endl);
1965 }
1966
1967 if (zone.isRoot()) {
1968 /* No TA for the root */
1969 return Insecure;
1970 }
1971
1972 return Indeterminate;
1973 }
1974
1975 static size_t countSupportedDS(const dsmap_t& dsmap)
1976 {
1977 size_t count = 0;
1978
1979 for (const auto& ds : dsmap) {
1980 if (isSupportedDS(ds)) {
1981 count++;
1982 }
1983 }
1984
1985 return count;
1986 }
1987
1988 vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsigned int depth, bool bogusOnNXD, bool* foundCut)
1989 {
1990 vState result = getTA(zone, ds);
1991
1992 if (result != Indeterminate || taOnly) {
1993 if (foundCut) {
1994 *foundCut = (result != Indeterminate);
1995 }
1996
1997 if (result == TA) {
1998 if (countSupportedDS(ds) == 0) {
1999 ds.clear();
2000 result = Insecure;
2001 }
2002 else {
2003 result = Secure;
2004 }
2005 }
2006 else if (result == NTA) {
2007 result = Insecure;
2008 }
2009
2010 return result;
2011 }
2012
2013 bool oldSkipCNAME = d_skipCNAMECheck;
2014 d_skipCNAMECheck = true;
2015
2016 std::set<GetBestNSAnswer> beenthere;
2017 std::vector<DNSRecord> dsrecords;
2018
2019 vState state = Indeterminate;
2020 int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state);
2021 d_skipCNAMECheck = oldSkipCNAME;
2022
2023 if (rcode == RCode::NoError || (rcode == RCode::NXDomain && !bogusOnNXD)) {
2024 uint8_t bestDigestType = 0;
2025
2026 bool gotCNAME = false;
2027 for (const auto& record : dsrecords) {
2028 if (record.d_type == QType::DS) {
2029 const auto dscontent = getRR<DSRecordContent>(record);
2030 if (dscontent && isSupportedDS(*dscontent)) {
2031 // Make GOST a lower prio than SHA256
2032 if (dscontent->d_digesttype == DNSSECKeeper::DIGEST_GOST && bestDigestType == DNSSECKeeper::DIGEST_SHA256) {
2033 continue;
2034 }
2035 if (dscontent->d_digesttype > bestDigestType || (bestDigestType == DNSSECKeeper::DIGEST_GOST && dscontent->d_digesttype == DNSSECKeeper::DIGEST_SHA256)) {
2036 bestDigestType = dscontent->d_digesttype;
2037 }
2038 ds.insert(*dscontent);
2039 }
2040 }
2041 else if (record.d_type == QType::CNAME && record.d_name == zone) {
2042 gotCNAME = true;
2043 }
2044 }
2045
2046 /* RFC 4509 section 3: "Validator implementations SHOULD ignore DS RRs containing SHA-1
2047 * digests if DS RRs with SHA-256 digests are present in the DS RRset."
2048 * As SHA348 is specified as well, the spirit of the this line is "use the best algorithm".
2049 */
2050 for (auto dsrec = ds.begin(); dsrec != ds.end(); ) {
2051 if (dsrec->d_digesttype != bestDigestType) {
2052 dsrec = ds.erase(dsrec);
2053 }
2054 else {
2055 ++dsrec;
2056 }
2057 }
2058
2059 if (rcode == RCode::NoError) {
2060 if (ds.empty()) {
2061 /* we have no DS, it's either:
2062 - a delegation to a non-DNSSEC signed zone
2063 - no delegation, we stay in the same zone
2064 */
2065 if (gotCNAME || denialProvesNoDelegation(zone, dsrecords)) {
2066 /* we are still inside the same zone */
2067
2068 if (foundCut) {
2069 *foundCut = false;
2070 }
2071 return state;
2072 }
2073
2074 /* delegation with no DS, might be Secure -> Insecure */
2075 if (foundCut) {
2076 *foundCut = true;
2077 }
2078
2079 /* a delegation with no DS is either:
2080 - a signed zone (Secure) to an unsigned one (Insecure)
2081 - an unsigned zone to another unsigned one (Insecure stays Insecure, Bogus stays Bogus)
2082 */
2083 return state == Secure ? Insecure : state;
2084 } else {
2085 /* we have a DS */
2086 if (foundCut) {
2087 *foundCut = true;
2088 }
2089 }
2090 }
2091
2092 return state;
2093 }
2094
2095 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
2096 return Bogus;
2097 }
2098
2099 bool SyncRes::haveExactValidationStatus(const DNSName& domain)
2100 {
2101 if (!shouldValidate()) {
2102 return false;
2103 }
2104 const auto& it = d_cutStates.find(domain);
2105 if (it != d_cutStates.cend()) {
2106 return true;
2107 }
2108 return false;
2109 }
2110
2111 vState SyncRes::getValidationStatus(const DNSName& subdomain, bool allowIndeterminate)
2112 {
2113 vState result = Indeterminate;
2114
2115 if (!shouldValidate()) {
2116 return result;
2117 }
2118 DNSName name(subdomain);
2119 do {
2120 const auto& it = d_cutStates.find(name);
2121 if (it != d_cutStates.cend()) {
2122 if (allowIndeterminate || it->second != Indeterminate) {
2123 LOG(d_prefix<<": got status "<<vStates[it->second]<<" for name "<<subdomain<<" (from "<<name<<")"<<endl);
2124 return it->second;
2125 }
2126 }
2127 }
2128 while (name.chopOff());
2129
2130 return result;
2131 }
2132
2133 bool SyncRes::lookForCut(const DNSName& qname, unsigned int depth, const vState existingState, vState& newState)
2134 {
2135 bool foundCut = false;
2136 dsmap_t ds;
2137 vState dsState = getDSRecords(qname, ds, newState == Bogus || existingState == Insecure || existingState == Bogus, depth, false, &foundCut);
2138
2139 if (dsState != Indeterminate) {
2140 newState = dsState;
2141 }
2142
2143 return foundCut;
2144 }
2145
2146 void SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth)
2147 {
2148 if(!begin.isPartOf(end)) {
2149 LOG(d_prefix<<" "<<begin.toLogString()<<" is not part of "<<end.toLogString()<<endl);
2150 throw PDNSException(begin.toLogString() + " is not part of " + end.toLogString());
2151 }
2152
2153 if (d_cutStates.count(begin) != 0) {
2154 return;
2155 }
2156
2157 const bool oldCacheOnly = setCacheOnly(false);
2158
2159 dsmap_t ds;
2160 vState cutState = getDSRecords(end, ds, false, depth);
2161 LOG(d_prefix<<": setting cut state for "<<end<<" to "<<vStates[cutState]<<endl);
2162 d_cutStates[end] = cutState;
2163
2164 if (!shouldValidate()) {
2165 setCacheOnly(oldCacheOnly);
2166 return;
2167 }
2168
2169 DNSName qname(end);
2170 std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
2171
2172 bool oldSkipCNAME = d_skipCNAMECheck;
2173 d_skipCNAMECheck = true;
2174
2175 while(qname != begin) {
2176 if (labelsToAdd.empty())
2177 break;
2178
2179 qname.prependRawLabel(labelsToAdd.back());
2180 labelsToAdd.pop_back();
2181 LOG(d_prefix<<": - Looking for a cut at "<<qname<<endl);
2182
2183 const auto cutIt = d_cutStates.find(qname);
2184 if (cutIt != d_cutStates.cend()) {
2185 if (cutIt->second != Indeterminate) {
2186 LOG(d_prefix<<": - Cut already known at "<<qname<<endl);
2187 cutState = cutIt->second;
2188 continue;
2189 }
2190 }
2191
2192 /* no need to look for NS and DS if we are already insecure or bogus,
2193 just look for (N)TA
2194 */
2195 if (cutState == Insecure || cutState == Bogus) {
2196 dsmap_t cutDS;
2197 vState newState = getDSRecords(qname, cutDS, true, depth);
2198 if (newState == Indeterminate) {
2199 continue;
2200 }
2201
2202 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[newState]<<endl);
2203 cutState = newState;
2204
2205 d_cutStates[qname] = cutState;
2206
2207 continue;
2208 }
2209
2210 vState newState = Indeterminate;
2211 /* temporarily mark as Indeterminate, so that we won't enter an endless loop
2212 trying to determine that zone cut again. */
2213 d_cutStates[qname] = newState;
2214 bool foundCut = lookForCut(qname, depth + 1, cutState, newState);
2215 if (foundCut) {
2216 LOG(d_prefix<<": - Found cut at "<<qname<<endl);
2217 if (newState != Indeterminate) {
2218 cutState = newState;
2219 }
2220 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[cutState]<<endl);
2221 d_cutStates[qname] = cutState;
2222 }
2223 else {
2224 /* remove the temporary cut */
2225 LOG(d_prefix<<qname<<": removing cut state for "<<qname<<endl);
2226 d_cutStates.erase(qname);
2227 }
2228 }
2229
2230 d_skipCNAMECheck = oldSkipCNAME;
2231
2232 LOG(d_prefix<<": list of cuts from "<<begin<<" to "<<end<<endl);
2233 for (const auto& cut : d_cutStates) {
2234 if (cut.first.isRoot() || (begin.isPartOf(cut.first) && cut.first.isPartOf(end))) {
2235 LOG(" - "<<cut.first<<": "<<vStates[cut.second]<<endl);
2236 }
2237 }
2238 setCacheOnly(oldCacheOnly);
2239 }
2240
2241 vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth)
2242 {
2243 dsmap_t ds;
2244 if (!signatures.empty()) {
2245 DNSName signer = getSigner(signatures);
2246
2247 if (!signer.empty() && zone.isPartOf(signer)) {
2248 vState state = getDSRecords(signer, ds, false, depth);
2249
2250 if (state != Secure) {
2251 return state;
2252 }
2253 }
2254 }
2255
2256 skeyset_t tentativeKeys;
2257 sortedRecords_t toSign;
2258
2259 for (const auto& dnskey : dnskeys) {
2260 if (dnskey.d_type == QType::DNSKEY) {
2261 auto content = getRR<DNSKEYRecordContent>(dnskey);
2262 if (content) {
2263 tentativeKeys.insert(content);
2264 toSign.insert(content);
2265 }
2266 }
2267 }
2268
2269 LOG(d_prefix<<": trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
2270 skeyset_t validatedKeys;
2271 validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
2272
2273 LOG(d_prefix<<": we now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
2274
2275 /* if we found at least one valid RRSIG covering the set,
2276 all tentative keys are validated keys. Otherwise it means
2277 we haven't found at least one DNSKEY and a matching RRSIG
2278 covering this set, this looks Bogus. */
2279 if (validatedKeys.size() != tentativeKeys.size()) {
2280 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
2281 return Bogus;
2282 }
2283
2284 return Secure;
2285 }
2286
2287 vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth)
2288 {
2289 std::vector<DNSRecord> records;
2290 std::set<GetBestNSAnswer> beenthere;
2291 LOG(d_prefix<<"Retrieving DNSKeys for "<<signer<<endl);
2292
2293 vState state = Indeterminate;
2294 /* following CNAME might lead to us to the wrong DNSKEY */
2295 bool oldSkipCNAME = d_skipCNAMECheck;
2296 d_skipCNAMECheck = true;
2297 int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state);
2298 d_skipCNAMECheck = oldSkipCNAME;
2299
2300 if (rcode == RCode::NoError) {
2301 if (state == Secure) {
2302 for (const auto& key : records) {
2303 if (key.d_type == QType::DNSKEY) {
2304 auto content = getRR<DNSKEYRecordContent>(key);
2305 if (content) {
2306 keys.insert(content);
2307 }
2308 }
2309 }
2310 }
2311 LOG(d_prefix<<"Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<vStates[state]<<endl);
2312 return state;
2313 }
2314
2315 LOG(d_prefix<<"Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
2316 return Bogus;
2317 }
2318
2319 vState SyncRes::validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, const DNSName& name, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures)
2320 {
2321 skeyset_t keys;
2322 if (!signatures.empty()) {
2323 const DNSName signer = getSigner(signatures);
2324 if (!signer.empty() && name.isPartOf(signer)) {
2325 if ((qtype == QType::DNSKEY || qtype == QType::DS) && signer == qname) {
2326 /* we are already retrieving those keys, sorry */
2327 if (qtype == QType::DS) {
2328 /* something is very wrong */
2329 LOG(d_prefix<<"The DS for "<<qname<<" is signed by itself, going Bogus"<<endl);
2330 return Bogus;
2331 }
2332 return Indeterminate;
2333 }
2334 vState state = getDNSKeys(signer, keys, depth);
2335 if (state != Secure) {
2336 return state;
2337 }
2338 }
2339 } else {
2340 LOG(d_prefix<<"Bogus!"<<endl);
2341 return Bogus;
2342 }
2343
2344 sortedRecords_t recordcontents;
2345 for (const auto& record : records) {
2346 recordcontents.insert(record.d_content);
2347 }
2348
2349 LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
2350 if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
2351 LOG(d_prefix<<"Secure!"<<endl);
2352 return Secure;
2353 }
2354
2355 LOG(d_prefix<<"Bogus!"<<endl);
2356 return Bogus;
2357 }
2358
2359 static bool allowAdditionalEntry(std::unordered_set<DNSName>& allowedAdditionals, const DNSRecord& rec)
2360 {
2361 switch(rec.d_type) {
2362 case QType::MX:
2363 {
2364 if (auto mxContent = getRR<MXRecordContent>(rec)) {
2365 allowedAdditionals.insert(mxContent->d_mxname);
2366 }
2367 return true;
2368 }
2369 case QType::NS:
2370 {
2371 if (auto nsContent = getRR<NSRecordContent>(rec)) {
2372 allowedAdditionals.insert(nsContent->getNS());
2373 }
2374 return true;
2375 }
2376 case QType::SRV:
2377 {
2378 if (auto srvContent = getRR<SRVRecordContent>(rec)) {
2379 allowedAdditionals.insert(srvContent->d_target);
2380 }
2381 return true;
2382 }
2383 default:
2384 return false;
2385 }
2386 }
2387
2388 void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, bool rdQuery)
2389 {
2390 const bool wasForwardRecurse = wasForwarded && rdQuery;
2391 /* list of names for which we will allow A and AAAA records in the additional section
2392 to remain */
2393 std::unordered_set<DNSName> allowedAdditionals = { qname };
2394 bool haveAnswers = false;
2395 bool isNXDomain = false;
2396 bool isNXQType = false;
2397
2398 for(auto rec = lwr.d_records.begin(); rec != lwr.d_records.end(); ) {
2399
2400 if (rec->d_type == QType::OPT) {
2401 ++rec;
2402 continue;
2403 }
2404
2405 if (rec->d_class != QClass::IN) {
2406 LOG(prefix<<"Removing non internet-classed data received from "<<auth<<endl);
2407 rec = lwr.d_records.erase(rec);
2408 continue;
2409 }
2410
2411 if (rec->d_type == QType::ANY) {
2412 LOG(prefix<<"Removing 'ANY'-typed data received from "<<auth<<endl);
2413 rec = lwr.d_records.erase(rec);
2414 continue;
2415 }
2416
2417 if (!rec->d_name.isPartOf(auth)) {
2418 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);
2419 rec = lwr.d_records.erase(rec);
2420 continue;
2421 }
2422
2423 /* dealing with the records in answer */
2424 if (!(lwr.d_aabit || wasForwardRecurse) && rec->d_place == DNSResourceRecord::ANSWER) {
2425 /* for now we allow a CNAME for the exact qname in ANSWER with AA=0, because Amazon DNS servers
2426 are sending such responses */
2427 if (!(rec->d_type == QType::CNAME && qname == rec->d_name)) {
2428 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);
2429 rec = lwr.d_records.erase(rec);
2430 continue;
2431 }
2432 }
2433
2434 if (rec->d_type == QType::DNAME && (rec->d_place != DNSResourceRecord::ANSWER || !qname.isPartOf(rec->d_name))) {
2435 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);
2436 rec = lwr.d_records.erase(rec);
2437 continue;
2438 }
2439
2440 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)) {
2441 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
2442 rec = lwr.d_records.erase(rec);
2443 continue;
2444 }
2445
2446 if (rec->d_place == DNSResourceRecord::ANSWER && !haveAnswers) {
2447 haveAnswers = true;
2448 }
2449
2450 if (rec->d_place == DNSResourceRecord::ANSWER) {
2451 allowAdditionalEntry(allowedAdditionals, *rec);
2452 }
2453
2454 /* dealing with the records in authority */
2455 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) {
2456 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
2457 rec = lwr.d_records.erase(rec);
2458 continue;
2459 }
2460
2461 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::SOA) {
2462 if (!qname.isPartOf(rec->d_name)) {
2463 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
2464 rec = lwr.d_records.erase(rec);
2465 continue;
2466 }
2467
2468 if (!(lwr.d_aabit || wasForwardRecurse)) {
2469 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
2470 rec = lwr.d_records.erase(rec);
2471 continue;
2472 }
2473
2474 if (!haveAnswers) {
2475 if (lwr.d_rcode == RCode::NXDomain) {
2476 isNXDomain = true;
2477 }
2478 else if (lwr.d_rcode == RCode::NoError) {
2479 isNXQType = true;
2480 }
2481 }
2482 }
2483
2484 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::NS && (isNXDomain || isNXQType)) {
2485 /* we don't want to pick up NS records in AUTHORITY or ADDITIONAL sections of NXDomain answers
2486 because they are somewhat easy to insert into a large, fragmented UDP response
2487 for an off-path attacker by injecting spoofed UDP fragments.
2488 */
2489 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);
2490 rec = lwr.d_records.erase(rec);
2491 continue;
2492 }
2493
2494 if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::NS) {
2495 allowAdditionalEntry(allowedAdditionals, *rec);
2496 }
2497
2498 /* dealing with the records in additional */
2499 if (rec->d_place == DNSResourceRecord::ADDITIONAL && rec->d_type != QType::A && rec->d_type != QType::AAAA && rec->d_type != QType::RRSIG) {
2500 LOG(prefix<<"Removing irrelevant record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
2501 rec = lwr.d_records.erase(rec);
2502 continue;
2503 }
2504
2505 if (rec->d_place == DNSResourceRecord::ADDITIONAL && allowedAdditionals.count(rec->d_name) == 0) {
2506 LOG(prefix<<"Removing irrelevant additional record '"<<rec->d_name<<"|"<<DNSRecordContent::NumberToType(rec->d_type)<<"|"<<rec->d_content->getZoneRepresentation()<<"' in the "<<(int)rec->d_place<<" section received from "<<auth<<endl);
2507 rec = lwr.d_records.erase(rec);
2508 continue;
2509 }
2510
2511 ++rec;
2512 }
2513 }
2514
2515 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)
2516 {
2517 bool wasForwardRecurse = wasForwarded && rdQuery;
2518 tcache_t tcache;
2519
2520 string prefix;
2521 if(doLog()) {
2522 prefix=d_prefix;
2523 prefix.append(depth, ' ');
2524 }
2525
2526 sanitizeRecords(prefix, lwr, qname, qtype, auth, wasForwarded, rdQuery);
2527
2528 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
2529 const unsigned int labelCount = qname.countLabels();
2530 bool isCNAMEAnswer = false;
2531 bool isDNAMEAnswer = false;
2532 for(const auto& rec : lwr.d_records) {
2533 if (rec.d_class != QClass::IN) {
2534 continue;
2535 }
2536
2537 if(!isCNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname && !isDNAMEAnswer) {
2538 isCNAMEAnswer = true;
2539 }
2540 if(!isDNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::DNAME && qtype != QType(QType::DNAME) && qname.isPartOf(rec.d_name)) {
2541 isDNAMEAnswer = true;
2542 isCNAMEAnswer = false;
2543 }
2544
2545 /* if we have a positive answer synthetized from a wildcard,
2546 we need to store the corresponding NSEC/NSEC3 records proving
2547 that the exact name did not exist in the negative cache */
2548 if(gatherWildcardProof) {
2549 if (nsecTypes.count(rec.d_type)) {
2550 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
2551 }
2552 else if (rec.d_type == QType::RRSIG) {
2553 auto rrsig = getRR<RRSIGRecordContent>(rec);
2554 if (rrsig && nsecTypes.count(rrsig->d_type)) {
2555 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
2556 }
2557 }
2558 }
2559 if(rec.d_type == QType::RRSIG) {
2560 auto rrsig = getRR<RRSIGRecordContent>(rec);
2561 if (rrsig) {
2562 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
2563 count can be lower than the name's label count if it was
2564 synthetized from the wildcard. Note that the difference might
2565 be > 1. */
2566 if (rec.d_name == qname && isWildcardExpanded(labelCount, rrsig)) {
2567 gatherWildcardProof = true;
2568 if (!isWildcardExpandedOntoItself(rec.d_name, labelCount, rrsig)) {
2569 /* if we have a wildcard expanded onto itself, we don't need to prove
2570 that the exact name doesn't exist because it actually does.
2571 We still want to gather the corresponding NSEC/NSEC3 records
2572 to pass them to our client in case it wants to validate by itself.
2573 */
2574 LOG(prefix<<qname<<": RRSIG indicates the name was synthetized from a wildcard, we need a wildcard proof"<<endl);
2575 needWildcardProof = true;
2576 }
2577 else {
2578 LOG(prefix<<qname<<": RRSIG indicates the name was synthetized from a wildcard expanded onto itself, we need to gather wildcard proof"<<endl);
2579 }
2580 wildcardLabelsCount = rrsig->d_labels;
2581 }
2582
2583 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
2584 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
2585 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);
2586 }
2587 }
2588 }
2589
2590 // reap all answers from this packet that are acceptable
2591 for(auto& rec : lwr.d_records) {
2592 if(rec.d_type == QType::OPT) {
2593 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
2594 continue;
2595 }
2596 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<<" ");
2597 if(rec.d_type == QType::ANY) {
2598 LOG("NO! - we don't accept 'ANY'-typed data"<<endl);
2599 continue;
2600 }
2601
2602 if(rec.d_class != QClass::IN) {
2603 LOG("NO! - we don't accept records for any other class than 'IN'"<<endl);
2604 continue;
2605 }
2606
2607 if (!(lwr.d_aabit || wasForwardRecurse) && rec.d_place == DNSResourceRecord::ANSWER) {
2608 /* for now we allow a CNAME for the exact qname in ANSWER with AA=0, because Amazon DNS servers
2609 are sending such responses */
2610 if (!(rec.d_type == QType::CNAME && rec.d_name == qname)) {
2611 LOG("NO! - we don't accept records in the answers section without the AA bit set"<<endl);
2612 continue;
2613 }
2614 }
2615
2616 if(rec.d_name.isPartOf(auth)) {
2617 if(rec.d_type == QType::RRSIG) {
2618 LOG("RRSIG - separate"<<endl);
2619 }
2620 else if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && rec.d_place==DNSResourceRecord::ANSWER && ((rec.d_type != QType::DNSKEY && rec.d_type != QType::DS) || rec.d_name != auth) && s_delegationOnly.count(auth)) {
2621 LOG("NO! Is from delegation-only zone"<<endl);
2622 s_nodelegated++;
2623 return RCode::NXDomain;
2624 }
2625 else {
2626 bool haveLogged = false;
2627 if (isDNAMEAnswer && rec.d_type == QType::CNAME) {
2628 LOG("NO - we already have a DNAME answer for this domain");
2629 continue;
2630 }
2631 if (!t_sstorage.domainmap->empty()) {
2632 // Check if we are authoritative for a zone in this answer
2633 DNSName tmp_qname(rec.d_name);
2634 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
2635 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
2636 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
2637 if (auth_domain_iter->first != auth) {
2638 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
2639 continue;
2640 } else {
2641 LOG("YES! - This answer was ");
2642 if (!wasForwarded) {
2643 LOG("retrieved from the local auth store.");
2644 } else {
2645 LOG("received from a server we forward to.");
2646 }
2647 haveLogged = true;
2648 LOG(endl);
2649 }
2650 }
2651 }
2652 if (!haveLogged) {
2653 LOG("YES!"<<endl);
2654 }
2655
2656 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
2657
2658 DNSRecord dr(rec);
2659 dr.d_ttl += d_now.tv_sec;
2660 dr.d_place=DNSResourceRecord::ANSWER;
2661 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
2662 }
2663 }
2664 else
2665 LOG("NO!"<<endl);
2666 }
2667
2668 // supplant
2669 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2670 if((i->second.records.size() + i->second.signatures.size()) > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
2671 uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
2672
2673 for(auto& record : i->second.records)
2674 record.d_ttl = lowestTTD; // boom
2675 }
2676
2677 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
2678 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
2679 }
2680
2681 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2682
2683 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
2684 continue;
2685
2686 /* Even if the AA bit is set, additional data cannot be considered
2687 as authoritative. This is especially important during validation
2688 because keeping records in the additional section is allowed even
2689 if the corresponding RRSIGs are not included, without setting the TC
2690 bit, as stated in rfc4035's section 3.1.1. Including RRSIG RRs in a Response:
2691 "When placing a signed RRset in the Additional section, the name
2692 server MUST also place its RRSIG RRs in the Additional section.
2693 If space does not permit inclusion of both the RRset and its
2694 associated RRSIG RRs, the name server MAY retain the RRset while
2695 dropping the RRSIG RRs. If this happens, the name server MUST NOT
2696 set the TC bit solely because these RRSIG RRs didn't fit."
2697 */
2698 bool isAA = lwr.d_aabit && i->first.place != DNSResourceRecord::ADDITIONAL;
2699 /* if we forwarded the query to a recursor, we can expect the answer to be signed,
2700 even if the answer is not AA. Of course that's not only true inside a Secure
2701 zone, but we check that below. */
2702 bool expectSignature = i->first.place == DNSResourceRecord::ANSWER || ((lwr.d_aabit || wasForwardRecurse) && i->first.place != DNSResourceRecord::ADDITIONAL);
2703 if (isCNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER || i->first.type != QType::CNAME || i->first.name != qname)) {
2704 /*
2705 rfc2181 states:
2706 Note that the answer section of an authoritative answer normally
2707 contains only authoritative data. However when the name sought is an
2708 alias (see section 10.1.1) only the record describing that alias is
2709 necessarily authoritative. Clients should assume that other records
2710 may have come from the server's cache. Where authoritative answers
2711 are required, the client should query again, using the canonical name
2712 associated with the alias.
2713 */
2714 isAA = false;
2715 expectSignature = false;
2716 }
2717
2718 if (isCNAMEAnswer && i->first.place == DNSResourceRecord::AUTHORITY && i->first.type == QType::NS && auth == i->first.name) {
2719 /* These NS can't be authoritative since we have a CNAME answer for which (see above) only the
2720 record describing that alias is necessarily authoritative.
2721 But if we allow the current auth, which might be serving the child zone, to raise the TTL
2722 of non-authoritative NS in the cache, they might be able to keep a "ghost" zone alive forever,
2723 even after the delegation is gone from the parent.
2724 So let's just do nothing with them, we can fetch them directly if we need them.
2725 */
2726 LOG(d_prefix<<": skipping authority NS from '"<<auth<<"' nameservers in CNAME answer "<<i->first.name<<"|"<<DNSRecordContent::NumberToType(i->first.type)<<endl);
2727 continue;
2728 }
2729
2730 vState recordState = getValidationStatus(i->first.name, false);
2731 LOG(d_prefix<<": got initial zone status "<<vStates[recordState]<<" for record "<<i->first.name<<"|"<<DNSRecordContent::NumberToType(i->first.type)<<endl);
2732
2733 if (shouldValidate() && recordState == Secure) {
2734 vState initialState = recordState;
2735
2736 if (expectSignature) {
2737 if (i->first.place != DNSResourceRecord::ADDITIONAL) {
2738 /* the additional entries can be insecure,
2739 like glue:
2740 "Glue address RRsets associated with delegations MUST NOT be signed"
2741 */
2742 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) {
2743 LOG(d_prefix<<"Validating DNSKEY for "<<i->first.name<<endl);
2744 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth);
2745 }
2746 else {
2747 /*
2748 * RFC 6672 section 5.3.1
2749 * In any response, a signed DNAME RR indicates a non-terminal
2750 * redirection of the query. There might or might not be a server-
2751 * synthesized CNAME in the answer section; if there is, the CNAME will
2752 * never be signed. For a DNSSEC validator, verification of the DNAME
2753 * RR and then that the CNAME was properly synthesized is sufficient
2754 * proof.
2755 *
2756 * We do the synthesis check in processRecords, here we make sure we
2757 * don't validate the CNAME.
2758 */
2759 if (!(isDNAMEAnswer && i->first.type == QType::CNAME)) {
2760 LOG(d_prefix<<"Validating non-additional record for "<<i->first.name<<endl);
2761 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2762 /* we might have missed a cut (zone cut within the same auth servers), causing the NS query for an Insecure zone to seem Bogus during zone cut determination */
2763 if (qtype == QType::NS && i->second.signatures.empty() && recordState == Bogus && haveExactValidationStatus(i->first.name) && getValidationStatus(i->first.name) == Indeterminate) {
2764 recordState = Indeterminate;
2765 }
2766 }
2767 }
2768 }
2769 }
2770 else {
2771 recordState = Indeterminate;
2772
2773 /* in a non authoritative answer, we only care about the DS record (or lack of) */
2774 if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
2775 LOG(d_prefix<<"Validating DS record for "<<i->first.name<<endl);
2776 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2777 }
2778 }
2779
2780 if (initialState == Secure && state != recordState && expectSignature) {
2781 updateValidationState(state, recordState);
2782 }
2783 }
2784 else {
2785 if (shouldValidate()) {
2786 LOG(d_prefix<<"Skipping validation because the current state is "<<vStates[recordState]<<endl);
2787 }
2788 }
2789
2790 if (recordState == Bogus) {
2791 /* this is a TTD by now, be careful */
2792 for(auto& record : i->second.records) {
2793 record.d_ttl = std::min(record.d_ttl, static_cast<uint32_t>(s_maxbogusttl + d_now.tv_sec));
2794 }
2795 }
2796
2797 /* We don't need to store NSEC3 records in the positive cache because:
2798 - we don't allow direct NSEC3 queries
2799 - denial of existence proofs in wildcard expanded positive responses are stored in authorityRecs
2800 - denial of existence proofs for negative responses are stored in the negative cache
2801 We also don't want to cache non-authoritative data except for:
2802 - records coming from non forward-recurse servers (those will never be AA)
2803 - DS (special case)
2804 - NS, A and AAAA (used for infra queries)
2805 */
2806 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)) {
2807
2808 bool doCache = true;
2809 if (i->first.place == DNSResourceRecord::ANSWER && ednsmask) {
2810 // If ednsmask is relevant, we do not want to cache if the scope prefix length is large and TTL is small
2811 if (SyncRes::s_ecscachelimitttl > 0) {
2812 bool manyMaskBits = (ednsmask->isIPv4() && ednsmask->getBits() > SyncRes::s_ecsipv4cachelimit) ||
2813 (ednsmask->isIPv6() && ednsmask->getBits() > SyncRes::s_ecsipv6cachelimit);
2814
2815 if (manyMaskBits) {
2816 uint32_t minttl = UINT32_MAX;
2817 for (const auto &it : i->second.records) {
2818 if (it.d_ttl < minttl)
2819 minttl = it.d_ttl;
2820 }
2821 bool ttlIsSmall = minttl < SyncRes::s_ecscachelimitttl + d_now.tv_sec;
2822 if (ttlIsSmall) {
2823 // Case: many bits and ttlIsSmall
2824 doCache = false;
2825 }
2826 }
2827 }
2828 }
2829 if (doCache) {
2830 s_RC->replace(d_now.tv_sec, i->first.name, QType(i->first.type), i->second.records, i->second.signatures, authorityRecs, i->first.type == QType::DS ? true : isAA, i->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none, recordState);
2831 }
2832 }
2833
2834 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
2835 d_wasVariable=true;
2836 }
2837
2838 return RCode::NoError;
2839 }
2840
2841 void SyncRes::updateDenialValidationState(vState& neValidationState, const DNSName& neName, vState& state, const dState denialState, const dState expectedState, bool allowOptOut)
2842 {
2843 if (denialState == expectedState) {
2844 neValidationState = Secure;
2845 }
2846 else {
2847 if (denialState == OPTOUT && allowOptOut) {
2848 LOG(d_prefix<<"OPT-out denial found for "<<neName<<endl);
2849 /* rfc5155 states:
2850 "The AD bit, as defined by [RFC4035], MUST NOT be set when returning a
2851 response containing a closest (provable) encloser proof in which the
2852 NSEC3 RR that covers the "next closer" name has the Opt-Out bit set.
2853
2854 This rule is based on what this closest encloser proof actually
2855 proves: names that would be covered by the Opt-Out NSEC3 RR may or
2856 may not exist as insecure delegations. As such, not all the data in
2857 responses containing such closest encloser proofs will have been
2858 cryptographically verified, so the AD bit cannot be set."
2859
2860 At best the Opt-Out NSEC3 RR proves that there is no signed DS (so no
2861 secure delegation).
2862 */
2863 neValidationState = Insecure;
2864 }
2865 else if (denialState == INSECURE) {
2866 LOG(d_prefix<<"Insecure denial found for "<<neName<<", returning Insecure"<<endl);
2867 neValidationState = Insecure;
2868 }
2869 else {
2870 LOG(d_prefix<<"Invalid denial found for "<<neName<<", returning Bogus, res="<<denialState<<", expectedState="<<expectedState<<endl);
2871 neValidationState = Bogus;
2872 }
2873 updateValidationState(state, neValidationState);
2874 }
2875 }
2876
2877 dState SyncRes::getDenialValidationState(const NegCache::NegCacheEntry& ne, const vState state, const dState expectedState, bool referralToUnsigned)
2878 {
2879 cspmap_t csp = harvestCSPFromNE(ne);
2880 return getDenial(csp, ne.d_name, ne.d_qtype.getCode(), referralToUnsigned, expectedState == NXQTYPE);
2881 }
2882
2883 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)
2884 {
2885 bool done = false;
2886 DNSName dnameTarget, dnameOwner;
2887 uint32_t dnameTTL = 0;
2888
2889 for(auto& rec : lwr.d_records) {
2890 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
2891 continue;
2892
2893 if (rec.d_place==DNSResourceRecord::ANSWER && !(lwr.d_aabit || sendRDQuery)) {
2894 /* for now we allow a CNAME for the exact qname in ANSWER with AA=0, because Amazon DNS servers
2895 are sending such responses */
2896 if (!(rec.d_type == QType::CNAME && rec.d_name == qname)) {
2897 continue;
2898 }
2899 }
2900
2901 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2902 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
2903 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
2904
2905 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
2906 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
2907 ret.push_back(rec);
2908
2909 NegCache::NegCacheEntry ne;
2910
2911 uint32_t lowestTTL = rec.d_ttl;
2912 /* if we get an NXDomain answer with a CNAME, the name
2913 does exist but the target does not */
2914 ne.d_name = newtarget.empty() ? qname : newtarget;
2915 ne.d_qtype = QType(0); // this encodes 'whole record'
2916 ne.d_auth = rec.d_name;
2917 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2918
2919 if (state == Secure) {
2920 dState denialState = getDenialValidationState(ne, state, NXDOMAIN, false);
2921 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, NXDOMAIN, true);
2922 }
2923 else {
2924 ne.d_validationState = state;
2925 }
2926
2927 if (ne.d_validationState == Bogus) {
2928 lowestTTL = min(lowestTTL, s_maxbogusttl);
2929 }
2930
2931 ne.d_ttd = d_now.tv_sec + lowestTTL;
2932 /* if we get an NXDomain answer with a CNAME, let's not cache the
2933 target, even the server was authoritative for it,
2934 and do an additional query for the CNAME target.
2935 We have a regression test making sure we do exactly that.
2936 */
2937 if(!wasVariable() && newtarget.empty()) {
2938 t_sstorage.negcache.add(ne);
2939 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot() && lwr.d_aabit) {
2940 ne.d_name = ne.d_name.getLastLabel();
2941 t_sstorage.negcache.add(ne);
2942 }
2943 }
2944
2945 negindic=true;
2946 }
2947 else if(rec.d_place==DNSResourceRecord::ANSWER && s_redirectionQTypes.count(rec.d_type) > 0 && // CNAME or DNAME answer
2948 s_redirectionQTypes.count(qtype.getCode()) == 0) { // But not in response to a CNAME or DNAME query
2949 if (rec.d_type == QType::CNAME && rec.d_name == qname) {
2950 if (!dnameOwner.empty()) { // We synthesize ourselves
2951 continue;
2952 }
2953 ret.push_back(rec);
2954 if (auto content = getRR<CNAMERecordContent>(rec)) {
2955 newtarget=content->getTarget();
2956 }
2957 } else if (rec.d_type == QType::DNAME && qname.isPartOf(rec.d_name)) { // DNAME
2958 ret.push_back(rec);
2959 if (auto content = getRR<DNAMERecordContent>(rec)) {
2960 dnameOwner = rec.d_name;
2961 dnameTarget = content->getTarget();
2962 dnameTTL = rec.d_ttl;
2963 if (!newtarget.empty()) { // We had a CNAME before, remove it from ret so we don't cache it
2964 ret.erase(std::remove_if(
2965 ret.begin(),
2966 ret.end(),
2967 [&qname](DNSRecord& rr) {
2968 return (rr.d_place == DNSResourceRecord::ANSWER && rr.d_type == QType::CNAME && rr.d_name == qname);
2969 }),
2970 ret.end());
2971 }
2972 try {
2973 newtarget = qname.makeRelative(dnameOwner) + dnameTarget;
2974 } catch (const std::exception &e) {
2975 // We should probably catch an std::range_error here and set the rcode to YXDOMAIN (RFC 6672, section 2.2)
2976 // But there is no way to set the RCODE from this function
2977 throw ImmediateServFailException("Unable to perform DNAME substitution(DNAME owner: '" + dnameOwner.toLogString() +
2978 "', DNAME target: '" + dnameTarget.toLogString() + "', substituted name: '" +
2979 qname.makeRelative(dnameOwner).toLogString() + "." + dnameTarget.toLogString() +
2980 "' : " + e.what());
2981 }
2982 }
2983 }
2984 }
2985 /* if we have a positive answer synthetized from a wildcard, we need to
2986 return the corresponding NSEC/NSEC3 records from the AUTHORITY section
2987 proving that the exact name did not exist */
2988 else if(gatherWildcardProof && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::AUTHORITY) {
2989 ret.push_back(rec); // enjoy your DNSSEC
2990 }
2991 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
2992 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
2993 (
2994 rec.d_type==qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType(QType::ANY))
2995 )
2996 )
2997 {
2998 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
2999
3000 done=true;
3001
3002 if (state == Secure && needWildcardProof) {
3003 /* We have a positive answer synthetized from a wildcard, we need to check that we have
3004 proof that the exact name doesn't exist so the wildcard can be used,
3005 as described in section 5.3.4 of RFC 4035 and 5.3 of RFC 7129.
3006 */
3007 NegCache::NegCacheEntry ne;
3008
3009 uint32_t lowestTTL = rec.d_ttl;
3010 ne.d_name = qname;
3011 ne.d_qtype = QType(0); // this encodes 'whole record'
3012 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
3013
3014 cspmap_t csp = harvestCSPFromNE(ne);
3015 dState res = getDenial(csp, qname, ne.d_qtype.getCode(), false, false, false, wildcardLabelsCount);
3016 if (res != NXDOMAIN) {
3017 vState st = Bogus;
3018 if (res == INSECURE) {
3019 /* Some part could not be validated, for example a NSEC3 record with a too large number of iterations,
3020 this is not enough to warrant a Bogus, but go Insecure. */
3021 st = Insecure;
3022 LOG(d_prefix<<"Unable to validate denial in wildcard expanded positive response found for "<<qname<<", returning Insecure, res="<<res<<endl);
3023 }
3024 else {
3025 LOG(d_prefix<<"Invalid denial in wildcard expanded positive response found for "<<qname<<", returning Bogus, res="<<res<<endl);
3026 rec.d_ttl = std::min(rec.d_ttl, s_maxbogusttl);
3027 }
3028
3029 updateValidationState(state, st);
3030 /* we already stored the record with a different validation status, let's fix it */
3031 updateValidationStatusInCache(qname, qtype, lwr.d_aabit, st);
3032 }
3033 }
3034 ret.push_back(rec);
3035 }
3036 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER) {
3037 if(rec.d_type != QType::RRSIG || rec.d_name == qname) {
3038 ret.push_back(rec); // enjoy your DNSSEC
3039 } else if(rec.d_type == QType::RRSIG && qname.isPartOf(rec.d_name)) {
3040 auto rrsig = getRR<RRSIGRecordContent>(rec);
3041 if (rrsig != nullptr && rrsig->d_type == QType::DNAME) {
3042 ret.push_back(rec);
3043 }
3044 }
3045 }
3046 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::NS && qname.isPartOf(rec.d_name)) {
3047 if(moreSpecificThan(rec.d_name,auth)) {
3048 newauth=rec.d_name;
3049 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
3050 realreferral=true;
3051 }
3052 else {
3053 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
3054 }
3055 if (auto content = getRR<NSRecordContent>(rec)) {
3056 nsset.insert(content->getNS());
3057 }
3058 }
3059 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
3060 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
3061 }
3062 else if(realreferral && rec.d_place==DNSResourceRecord::AUTHORITY && (rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && newauth.isPartOf(auth)) {
3063 /* we might have received a denial of the DS, let's check */
3064 if (state == Secure) {
3065 NegCache::NegCacheEntry ne;
3066 ne.d_auth = auth;
3067 ne.d_name = newauth;
3068 ne.d_qtype = QType::DS;
3069 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
3070 uint32_t lowestTTL = rec.d_ttl;
3071 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
3072
3073 dState denialState = getDenialValidationState(ne, state, NXQTYPE, true);
3074
3075 if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
3076 ne.d_ttd = lowestTTL + d_now.tv_sec;
3077 ne.d_validationState = Secure;
3078 if (denialState == OPTOUT) {
3079 ne.d_validationState = Insecure;
3080 }
3081 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
3082
3083 if(!wasVariable()) {
3084 t_sstorage.negcache.add(ne);
3085 }
3086
3087 if (qname == newauth && qtype == QType::DS) {
3088 /* we are actually done! */
3089 negindic=true;
3090 nsset.clear();
3091 }
3092 }
3093 }
3094 }
3095 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
3096 lwr.d_rcode==RCode::NoError && qname.isPartOf(rec.d_name)) {
3097 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
3098
3099 if(!newtarget.empty()) {
3100 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
3101 }
3102 else {
3103 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
3104
3105 NegCache::NegCacheEntry ne;
3106 ne.d_auth = rec.d_name;
3107 uint32_t lowestTTL = rec.d_ttl;
3108 ne.d_name = qname;
3109 ne.d_qtype = qtype;
3110 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
3111
3112 if (state == Secure) {
3113 dState denialState = getDenialValidationState(ne, state, NXQTYPE, false);
3114 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, NXQTYPE, qtype == QType::DS);
3115 } else {
3116 ne.d_validationState = state;
3117 }
3118
3119 if (ne.d_validationState == Bogus) {
3120 lowestTTL = min(lowestTTL, s_maxbogusttl);
3121 rec.d_ttl = min(rec.d_ttl, s_maxbogusttl);
3122 }
3123 ne.d_ttd = d_now.tv_sec + lowestTTL;
3124
3125 if(!wasVariable()) {
3126 if(qtype.getCode()) { // prevents us from blacking out a whole domain
3127 t_sstorage.negcache.add(ne);
3128 }
3129 }
3130
3131 ret.push_back(rec);
3132 negindic=true;
3133 }
3134 }
3135 }
3136
3137 if (!dnameTarget.empty()) {
3138 // Synthesize a CNAME
3139 auto cnamerec = DNSRecord();
3140 cnamerec.d_name = qname;
3141 cnamerec.d_type = QType::CNAME;
3142 cnamerec.d_ttl = dnameTTL;
3143 cnamerec.d_content = std::make_shared<CNAMERecordContent>(CNAMERecordContent(newtarget));
3144 ret.push_back(cnamerec);
3145 }
3146 return done;
3147 }
3148
3149 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 DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool* truncated)
3150 {
3151 bool chained = false;
3152 int resolveret = RCode::NoError;
3153 s_outqueries++;
3154 d_outqueries++;
3155
3156 if(d_outqueries + d_throttledqueries > s_maxqperq) {
3157 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
3158 }
3159
3160 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
3161 throw ImmediateServFailException("Too much time waiting for "+qname.toLogString()+"|"+qtype.getName()+", 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");
3162 }
3163
3164 if(doTCP) {
3165 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
3166 s_tcpoutqueries++;
3167 d_tcpoutqueries++;
3168 }
3169
3170 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
3171 LOG(prefix<<qname<<": query handled by Lua"<<endl);
3172 }
3173 else {
3174 ednsmask=getEDNSSubnetMask(qname, remoteIP);
3175 if(ednsmask) {
3176 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
3177 s_ecsqueries++;
3178 }
3179 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, auth, qtype.getCode(),
3180 doTCP, sendRDQuery, &d_now, ednsmask, &lwr, &chained); // <- we go out on the wire!
3181 if(ednsmask) {
3182 s_ecsresponses++;
3183 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
3184 if (ednsmask->getBits() > 0) {
3185 if (ednsmask->isIPv4()) {
3186 ++SyncRes::s_ecsResponsesBySubnetSize4.at(ednsmask->getBits()-1);
3187 }
3188 else {
3189 ++SyncRes::s_ecsResponsesBySubnetSize6.at(ednsmask->getBits()-1);
3190 }
3191 }
3192 }
3193 }
3194
3195 /* preoutquery killed the query by setting dq.rcode to -3 */
3196 if(resolveret==-3) {
3197 throw ImmediateServFailException("Query killed by policy");
3198 }
3199
3200 d_totUsec += lwr.d_usec;
3201 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
3202
3203 bool dontThrottle = false;
3204 {
3205 auto dontThrottleNames = g_dontThrottleNames.getLocal();
3206 auto dontThrottleNetmasks = g_dontThrottleNetmasks.getLocal();
3207 dontThrottle = dontThrottleNames->check(nsName) || dontThrottleNetmasks->match(remoteIP);
3208 }
3209
3210 if(resolveret != 1) {
3211 /* Error while resolving */
3212 if(resolveret == 0) {
3213 /* Time out */
3214
3215 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
3216 d_timeouts++;
3217 s_outgoingtimeouts++;
3218
3219 if(remoteIP.sin4.sin_family == AF_INET)
3220 s_outgoing4timeouts++;
3221 else
3222 s_outgoing6timeouts++;
3223
3224 if(t_timeouts)
3225 t_timeouts->push_back(remoteIP);
3226 }
3227 else if(resolveret == -2) {
3228 /* OS resource limit reached */
3229 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
3230 g_stats.resourceLimits++;
3231 }
3232 else {
3233 /* -1 means server unreachable */
3234 s_unreachables++;
3235 d_unreachables++;
3236 // XXX questionable use of errno
3237 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<stringerror()<< endl);
3238 }
3239
3240 if(resolveret != -2 && !chained && !dontThrottle) {
3241 // don't account for resource limits, they are our own fault
3242 // And don't throttle when the IP address is on the dontThrottleNetmasks list or the name is part of dontThrottleNames
3243 t_sstorage.nsSpeeds[nsName.empty()? DNSName(remoteIP.toStringWithPort()) : nsName].submit(remoteIP, 1000000, d_now); // 1 sec
3244
3245 // code below makes sure we don't filter COM or the root
3246 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP, d_now) >= s_serverdownmaxfails) {
3247 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
3248 // mark server as down
3249 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
3250 }
3251 else if (resolveret == -1) {
3252 // unreachable, 1 minute or 100 queries
3253 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
3254 }
3255 else {
3256 // timeout, 10 seconds or 5 queries
3257 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
3258 }
3259 }
3260
3261 return false;
3262 }
3263
3264 /* we got an answer */
3265 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
3266 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
3267 if (!chained && !dontThrottle) {
3268 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
3269 }
3270 return false;
3271 }
3272
3273 /* this server sent a valid answer, mark it backup up if it was down */
3274 if(s_serverdownmaxfails > 0) {
3275 t_sstorage.fails.clear(remoteIP);
3276 }
3277
3278 if(lwr.d_tcbit) {
3279 *truncated = true;
3280
3281 if (doTCP) {
3282 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
3283 if (!dontThrottle) {
3284 /* let's treat that as a ServFail answer from this server */
3285 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
3286 }
3287 return false;
3288 }
3289 LOG(prefix<<qname<<": truncated bit set, over UDP"<<endl);
3290
3291 return true;
3292 }
3293
3294 return true;
3295 }
3296
3297 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)
3298 {
3299 string prefix;
3300 if(doLog()) {
3301 prefix=d_prefix;
3302 prefix.append(depth, ' ');
3303 }
3304
3305 if(s_minimumTTL) {
3306 for(auto& rec : lwr.d_records) {
3307 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
3308 }
3309 }
3310
3311 /* if the answer is ECS-specific, a minimum TTL is set for this kind of answers
3312 and it's higher than the global minimum TTL */
3313 if (ednsmask && s_minimumECSTTL > 0 && (s_minimumTTL == 0 || s_minimumECSTTL > s_minimumTTL)) {
3314 for(auto& rec : lwr.d_records) {
3315 if (rec.d_place == DNSResourceRecord::ANSWER) {
3316 rec.d_ttl = max(rec.d_ttl, s_minimumECSTTL);
3317 }
3318 }
3319 }
3320
3321 bool needWildcardProof = false;
3322 bool gatherWildcardProof = false;
3323 unsigned int wildcardLabelsCount;
3324 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, needWildcardProof, gatherWildcardProof, wildcardLabelsCount, sendRDQuery);
3325 if (*rcode != RCode::NoError) {
3326 return true;
3327 }
3328
3329 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
3330
3331 set<DNSName> nsset;
3332 bool realreferral=false, negindic=false;
3333 DNSName newauth;
3334 DNSName newtarget;
3335
3336 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof, gatherWildcardProof, wildcardLabelsCount);
3337
3338 if(done){
3339 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
3340 LOG(prefix<<qname<<": validation status is "<<vStates[state]<<endl);
3341 *rcode = RCode::NoError;
3342 return true;
3343 }
3344
3345 if(!newtarget.empty()) {
3346 if(newtarget == qname) {
3347 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
3348 *rcode = RCode::ServFail;
3349 return true;
3350 }
3351
3352 if(depth > 10) {
3353 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
3354 *rcode = RCode::ServFail;
3355 return true;
3356 }
3357
3358 if (qtype == QType::DS) {
3359 LOG(prefix<<qname<<": status=got a CNAME referral, but we are looking for a DS"<<endl);
3360
3361 if(d_doDNSSEC)
3362 addNXNSECS(ret, lwr.d_records);
3363
3364 *rcode = RCode::NoError;
3365 return true;
3366 }
3367 else {
3368 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
3369
3370 set<GetBestNSAnswer> beenthere2;
3371 vState cnameState = Indeterminate;
3372 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState);
3373 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
3374 updateValidationState(state, cnameState);
3375 return true;
3376 }
3377 }
3378
3379 if(lwr.d_rcode == RCode::NXDomain) {
3380 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
3381
3382 if(d_doDNSSEC)
3383 addNXNSECS(ret, lwr.d_records);
3384
3385 *rcode = RCode::NXDomain;
3386 return true;
3387 }
3388
3389 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
3390 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
3391
3392 if(state == Secure && (lwr.d_aabit || sendRDQuery) && !negindic) {
3393 updateValidationState(state, Bogus);
3394 }
3395
3396 if(d_doDNSSEC)
3397 addNXNSECS(ret, lwr.d_records);
3398
3399 *rcode = RCode::NoError;
3400 return true;
3401 }
3402
3403 if(realreferral) {
3404 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
3405
3406 nameservers.clear();
3407 for (auto const &nameserver : nsset) {
3408 if (d_wantsRPZ && (d_appliedPolicy.d_type == DNSFilterEngine::PolicyType::None || d_appliedPolicy.d_kind == DNSFilterEngine::PolicyKind::NoAction)) {
3409 bool match = dfe.getProcessingPolicy(nameserver, d_discardedPolicies, d_appliedPolicy);
3410 if (match && d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
3411 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
3412 throw PolicyHitException();
3413 }
3414 }
3415 nameservers.insert({nameserver, {{}, false}});
3416 }
3417 LOG("looping to them"<<endl);
3418 *gotNewServers = true;
3419 auth=newauth;
3420
3421 return false;
3422 }
3423
3424 return false;
3425 }
3426
3427 /** returns:
3428 * -1 in case of no results
3429 * rcode otherwise
3430 */
3431 int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
3432 vector<DNSRecord>&ret,
3433 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state, StopAtDelegation* stopAtDelegation)
3434 {
3435 auto luaconfsLocal = g_luaconfs.getLocal();
3436 string prefix;
3437 if(doLog()) {
3438 prefix=d_prefix;
3439 prefix.append(depth, ' ');
3440 }
3441
3442 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
3443
3444 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
3445 /* RPZ hit */
3446 throw PolicyHitException();
3447 }
3448
3449 LOG(endl);
3450
3451 for(;;) { // we may get more specific nameservers
3452 auto rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
3453
3454 for(auto tns=rnameservers.cbegin();;++tns) {
3455 if(tns==rnameservers.cend()) {
3456 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
3457 if(!auth.isRoot() && flawedNSSet) {
3458 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
3459
3460 if(s_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
3461 g_stats.nsSetInvalidations++;
3462 }
3463 return -1;
3464 }
3465
3466 bool cacheOnly = false;
3467 // this line needs to identify the 'self-resolving' behaviour
3468 if(qname == tns->first && (qtype.getCode() == QType::A || qtype.getCode() == QType::AAAA)) {
3469 /* we might have a glue entry in cache so let's try this NS
3470 but only if we have enough in the cache to know how to reach it */
3471 LOG(prefix<<qname<<": Using NS to resolve itself, but only using what we have in cache ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
3472 cacheOnly = true;
3473 }
3474
3475 typedef vector<ComboAddress> remoteIPs_t;
3476 remoteIPs_t remoteIPs;
3477 remoteIPs_t::const_iterator remoteIP;
3478 bool pierceDontQuery=false;
3479 bool sendRDQuery=false;
3480 boost::optional<Netmask> ednsmask;
3481 LWResult lwr;
3482 const bool wasForwarded = tns->first.empty() && (!nameservers[tns->first].first.empty());
3483 int rcode = RCode::NoError;
3484 bool gotNewServers = false;
3485
3486 if(tns->first.empty() && !wasForwarded) {
3487 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
3488 /* setting state to indeterminate since validation is disabled for local auth zone,
3489 and Insecure would be misleading. */
3490 state = Indeterminate;
3491 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
3492 lwr.d_tcbit=false;
3493 lwr.d_aabit=true;
3494
3495 /* we have received an answer, are we done ? */
3496 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
3497 if (done) {
3498 return rcode;
3499 }
3500 if (gotNewServers) {
3501 if (stopAtDelegation && *stopAtDelegation == Stop) {
3502 *stopAtDelegation = Stopped;
3503 return rcode;
3504 }
3505 break;
3506 }
3507 }
3508 else {
3509 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
3510 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly);
3511
3512 if(remoteIPs.empty()) {
3513 LOG(prefix<<qname<<": Failed to get IP for NS "<<tns->first<<", trying next if available"<<endl);
3514 flawedNSSet=true;
3515 continue;
3516 }
3517 else {
3518 bool hitPolicy{false};
3519 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<tns->first<<" to: ");
3520 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
3521 if(remoteIP != remoteIPs.cbegin()) {
3522 LOG(", ");
3523 }
3524 LOG(remoteIP->toString());
3525 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
3526 hitPolicy = true;
3527 }
3528 }
3529 LOG(endl);
3530 if (hitPolicy) { //implies d_wantsRPZ
3531 /* RPZ hit */
3532 throw PolicyHitException();
3533 }
3534 }
3535
3536 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
3537 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
3538
3539 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
3540 continue;
3541 }
3542
3543 bool truncated = false;
3544 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
3545 tns->first, *remoteIP, false, &truncated);
3546 if (gotAnswer && truncated ) {
3547 /* retry, over TCP this time */
3548 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
3549 tns->first, *remoteIP, true, &truncated);
3550 }
3551
3552 if (!gotAnswer) {
3553 continue;
3554 }
3555
3556 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);
3557
3558 /* // for you IPv6 fanatics :-)
3559 if(remoteIP->sin4.sin_family==AF_INET6)
3560 lwr.d_usec/=3;
3561 */
3562 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
3563
3564 t_sstorage.nsSpeeds[tns->first.empty()? DNSName(remoteIP->toStringWithPort()) : tns->first].submit(*remoteIP, lwr.d_usec, d_now);
3565
3566 /* we have received an answer, are we done ? */
3567 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
3568 if (done) {
3569 return rcode;
3570 }
3571 if (gotNewServers) {
3572 if (stopAtDelegation && *stopAtDelegation == Stop) {
3573 *stopAtDelegation = Stopped;
3574 return rcode;
3575 }
3576 break;
3577 }
3578 /* was lame */
3579 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
3580 }
3581
3582 if (gotNewServers) {
3583 break;
3584 }
3585
3586 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
3587 continue;
3588
3589 }
3590 }
3591 }
3592 return -1;
3593 }
3594
3595 void SyncRes::setQuerySource(const ComboAddress& requestor, boost::optional<const EDNSSubnetOpts&> incomingECS)
3596 {
3597 d_requestor = requestor;
3598
3599 if (incomingECS && incomingECS->source.getBits() > 0) {
3600 d_cacheRemote = incomingECS->source.getMaskedNetwork();
3601 uint8_t bits = std::min(incomingECS->source.getBits(), (incomingECS->source.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
3602 ComboAddress trunc = incomingECS->source.getNetwork();
3603 trunc.truncate(bits);
3604 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
3605 } else {
3606 d_cacheRemote = d_requestor;
3607 if(!incomingECS && s_ednslocalsubnets.match(d_requestor)) {
3608 ComboAddress trunc = d_requestor;
3609 uint8_t bits = d_requestor.isIPv4() ? 32 : 128;
3610 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
3611 trunc.truncate(bits);
3612 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
3613 } else if (s_ecsScopeZero.source.getBits() > 0) {
3614 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0.
3615 But using an empty ECS in that case would mean inserting
3616 a non ECS-specific entry into the cache, preventing any further
3617 ECS-specific query to be sent.
3618 So instead we use the trick described in section 7.1.2:
3619 "The subsequent Recursive Resolver query to the Authoritative Nameserver
3620 will then either not include an ECS option or MAY optionally include
3621 its own address information, which is what the Authoritative
3622 Nameserver will almost certainly use to generate any Tailored
3623 Response in lieu of an option. This allows the answer to be handled
3624 by the same caching mechanism as other queries, with an explicit
3625 indicator of the applicable scope. Subsequent Stub Resolver queries
3626 for /0 can then be answered from this cached response.
3627 */
3628 d_outgoingECSNetwork = boost::optional<Netmask>(s_ecsScopeZero.source.getMaskedNetwork());
3629 d_cacheRemote = s_ecsScopeZero.source.getNetwork();
3630 } else {
3631 // ECS disabled because no scope-zero address could be derived.
3632 d_outgoingECSNetwork = boost::none;
3633 }
3634 }
3635 }
3636
3637 boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const DNSName& dn, const ComboAddress& rem)
3638 {
3639 if(d_outgoingECSNetwork && (s_ednsdomains.check(dn) || s_ednsremotesubnets.match(rem))) {
3640 return d_outgoingECSNetwork;
3641 }
3642 return boost::none;
3643 }
3644
3645 void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
3646 {
3647 vector<string> parts;
3648 stringtok(parts, wlist, ",; ");
3649 for(const auto& a : parts) {
3650 try {
3651 s_ednsremotesubnets.addMask(Netmask(a));
3652 }
3653 catch(...) {
3654 s_ednsdomains.add(DNSName(a));
3655 }
3656 }
3657 }
3658
3659 void SyncRes::parseEDNSSubnetAddFor(const std::string& subnetlist)
3660 {
3661 vector<string> parts;
3662 stringtok(parts, subnetlist, ",; ");
3663 for(const auto& a : parts) {
3664 s_ednslocalsubnets.addMask(a);
3665 }
3666 }
3667
3668 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
3669 int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
3670 {
3671 struct timeval now;
3672 gettimeofday(&now, 0);
3673
3674 SyncRes sr(now);
3675 int res = -1;
3676 try {
3677 res = sr.beginResolve(qname, QType(qtype), qclass, ret);
3678 }
3679 catch(const PDNSException& e) {
3680 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got pdns exception: "<<e.reason<<endl;
3681 ret.clear();
3682 }
3683 catch(const ImmediateServFailException& e) {
3684 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got ImmediateServFailException: "<<e.reason<<endl;
3685 ret.clear();
3686 }
3687 catch(const PolicyHitException& e) {
3688 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got a policy hit"<<endl;
3689 ret.clear();
3690 }
3691 catch(const std::exception& e) {
3692 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got STL error: "<<e.what()<<endl;
3693 ret.clear();
3694 }
3695 catch(...) {
3696 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got an exception"<<endl;
3697 ret.clear();
3698 }
3699
3700 return res;
3701 }
3702
3703 int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
3704 SyncRes sr(now);
3705 sr.setDoEDNS0(true);
3706 sr.setUpdatingRootNS();
3707 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
3708 sr.setDNSSECValidationRequested(g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate);
3709 sr.setAsyncCallback(asyncCallback);
3710
3711 vector<DNSRecord> ret;
3712 int res=-1;
3713 try {
3714 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
3715 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
3716 auto state = sr.getValidationState();
3717 if (state == Bogus)
3718 throw PDNSException("Got Bogus validation result for .|NS");
3719 }
3720 return res;
3721 }
3722 catch(const PDNSException& e) {
3723 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
3724 }
3725 catch(const ImmediateServFailException& e) {
3726 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
3727 }
3728 catch(const PolicyHitException& e) {
3729 g_log<<Logger::Error<<"Failed to update . records, got a policy hit"<<endl;
3730 ret.clear();
3731 }
3732 catch(const std::exception& e) {
3733 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
3734 }
3735 catch(...) {
3736 g_log<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
3737 }
3738
3739 if(!res) {
3740 g_log<<Logger::Notice<<"Refreshed . records"<<endl;
3741 }
3742 else
3743 g_log<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
3744
3745 return res;
3746 }