]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/syncres.cc
rec: Fix the computation of the closest encloser for positive answers
[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
41 std::unordered_set<DNSName> SyncRes::s_delegationOnly;
42 std::unique_ptr<NetmaskGroup> SyncRes::s_dontQuery{nullptr};
43 NetmaskGroup SyncRes::s_ednssubnets;
44 SuffixMatchNode SyncRes::s_ednsdomains;
45 EDNSSubnetOpts SyncRes::s_ecsScopeZero;
46 string SyncRes::s_serverID;
47 SyncRes::LogMode SyncRes::s_lm;
48
49 unsigned int SyncRes::s_maxnegttl;
50 unsigned int SyncRes::s_maxcachettl;
51 unsigned int SyncRes::s_maxqperq;
52 unsigned int SyncRes::s_maxtotusec;
53 unsigned int SyncRes::s_maxdepth;
54 unsigned int SyncRes::s_minimumTTL;
55 unsigned int SyncRes::s_packetcachettl;
56 unsigned int SyncRes::s_packetcacheservfailttl;
57 unsigned int SyncRes::s_serverdownmaxfails;
58 unsigned int SyncRes::s_serverdownthrottletime;
59 std::atomic<uint64_t> SyncRes::s_queries;
60 std::atomic<uint64_t> SyncRes::s_outgoingtimeouts;
61 std::atomic<uint64_t> SyncRes::s_outgoing4timeouts;
62 std::atomic<uint64_t> SyncRes::s_outgoing6timeouts;
63 std::atomic<uint64_t> SyncRes::s_outqueries;
64 std::atomic<uint64_t> SyncRes::s_tcpoutqueries;
65 std::atomic<uint64_t> SyncRes::s_throttledqueries;
66 std::atomic<uint64_t> SyncRes::s_dontqueries;
67 std::atomic<uint64_t> SyncRes::s_nodelegated;
68 std::atomic<uint64_t> SyncRes::s_unreachables;
69 std::atomic<uint64_t> SyncRes::s_ecsqueries;
70 std::atomic<uint64_t> SyncRes::s_ecsresponses;
71 uint8_t SyncRes::s_ecsipv4limit;
72 uint8_t SyncRes::s_ecsipv6limit;
73 bool SyncRes::s_doIPv6;
74 bool SyncRes::s_nopacketcache;
75 bool SyncRes::s_rootNXTrust;
76 bool SyncRes::s_noEDNS;
77
78 #define LOG(x) if(d_lm == Log) { L <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
79
80 static void accountAuthLatency(int usec, int family)
81 {
82 if(family == AF_INET) {
83 if(usec < 1000)
84 g_stats.auth4Answers0_1++;
85 else if(usec < 10000)
86 g_stats.auth4Answers1_10++;
87 else if(usec < 100000)
88 g_stats.auth4Answers10_100++;
89 else if(usec < 1000000)
90 g_stats.auth4Answers100_1000++;
91 else
92 g_stats.auth4AnswersSlow++;
93 } else {
94 if(usec < 1000)
95 g_stats.auth6Answers0_1++;
96 else if(usec < 10000)
97 g_stats.auth6Answers1_10++;
98 else if(usec < 100000)
99 g_stats.auth6Answers10_100++;
100 else if(usec < 1000000)
101 g_stats.auth6Answers100_1000++;
102 else
103 g_stats.auth6AnswersSlow++;
104 }
105
106 }
107
108
109 SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
110 d_totUsec(0), d_now(now),
111 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm)
112
113 {
114 }
115
116 /** everything begins here - this is the entry point just after receiving a packet */
117 int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
118 {
119 vState state = Indeterminate;
120 s_queries++;
121 d_wasVariable=false;
122 d_wasOutOfBand=false;
123
124 if (doSpecialNamesResolve(qname, qtype, qclass, ret)) {
125 d_queryValidationState = Insecure;
126 return 0;
127 }
128
129 if( (qtype.getCode() == QType::AXFR) || (qtype.getCode() == QType::IXFR) || (qtype.getCode() == QType::RRSIG) || (qtype.getCode() == QType::NSEC3))
130 return -1;
131
132 if(qclass==QClass::ANY)
133 qclass=QClass::IN;
134 else if(qclass!=QClass::IN)
135 return -1;
136
137 set<GetBestNSAnswer> beenthere;
138 int res=doResolve(qname, qtype, ret, 0, beenthere, state);
139 d_queryValidationState = state;
140
141 if (d_queryValidationState != Indeterminate) {
142 g_stats.dnssecValidations++;
143 }
144 if (shouldValidate()) {
145 increaseDNSSECStateCounter(d_queryValidationState);
146 }
147
148 return res;
149 }
150
151 /*! Handles all special, built-in names
152 * Fills ret with an answer and returns true if it handled the query.
153 *
154 * Handles the following queries (and their ANY variants):
155 *
156 * - localhost. IN A
157 * - localhost. IN AAAA
158 * - 1.0.0.127.in-addr.arpa. IN PTR
159 * - 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
160 * - version.bind. CH TXT
161 * - version.pdns. CH TXT
162 * - id.server. CH TXT
163 */
164 bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret)
165 {
166 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."),
167 localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns.");
168
169 bool handled = false;
170 vector<pair<QType::typeenum, string> > answers;
171
172 if ((qname == arpa || qname == ip6_arpa) &&
173 qclass == QClass::IN) {
174 handled = true;
175 if (qtype == QType::PTR || qtype == QType::ANY)
176 answers.push_back({QType::PTR, "localhost."});
177 }
178
179 if (qname == localhost &&
180 qclass == QClass::IN) {
181 handled = true;
182 if (qtype == QType::A || qtype == QType::ANY)
183 answers.push_back({QType::A, "127.0.0.1"});
184 if (qtype == QType::AAAA || qtype == QType::ANY)
185 answers.push_back({QType::AAAA, "::1"});
186 }
187
188 if ((qname == versionbind || qname == idserver || qname == versionpdns) &&
189 qclass == QClass::CHAOS) {
190 handled = true;
191 if (qtype == QType::TXT || qtype == QType::ANY) {
192 if(qname == versionbind || qname == versionpdns)
193 answers.push_back({QType::TXT, "\""+::arg()["version-string"]+"\""});
194 else
195 answers.push_back({QType::TXT, "\""+s_serverID+"\""});
196 }
197 }
198
199 if (handled && !answers.empty()) {
200 ret.clear();
201 d_wasOutOfBand=true;
202
203 DNSRecord dr;
204 dr.d_name = qname;
205 dr.d_place = DNSResourceRecord::ANSWER;
206 dr.d_class = qclass;
207 dr.d_ttl = 86400;
208 for (const auto& ans : answers) {
209 dr.d_type = ans.first;
210 dr.d_content = DNSRecordContent::mastermake(ans.first, qclass, ans.second);
211 ret.push_back(dr);
212 }
213 }
214
215 return handled;
216 }
217
218
219 //! This is the 'out of band resolver', in other words, the authoritative server
220 void SyncRes::AuthDomain::addSOA(std::vector<DNSRecord>& records) const
221 {
222 SyncRes::AuthDomain::records_t::const_iterator ziter = d_records.find(boost::make_tuple(getName(), QType::SOA));
223 if (ziter != d_records.end()) {
224 DNSRecord dr = *ziter;
225 dr.d_place = DNSResourceRecord::AUTHORITY;
226 records.push_back(dr);
227 }
228 else {
229 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
230 }
231 }
232
233 int SyncRes::AuthDomain::getRecords(const DNSName& qname, uint16_t qtype, std::vector<DNSRecord>& records) const
234 {
235 int result = RCode::NoError;
236 records.clear();
237
238 // partial lookup
239 std::pair<records_t::const_iterator,records_t::const_iterator> range = d_records.equal_range(tie(qname));
240
241 SyncRes::AuthDomain::records_t::const_iterator ziter;
242 bool somedata = false;
243
244 for(ziter = range.first; ziter != range.second; ++ziter) {
245 somedata = true;
246
247 if(qtype == QType::ANY || ziter->d_type == qtype || ziter->d_type == QType::CNAME) {
248 // let rest of nameserver do the legwork on this one
249 records.push_back(*ziter);
250 }
251 else if (ziter->d_type == QType::NS && ziter->d_name.countLabels() > getName().countLabels()) {
252 // we hit a delegation point!
253 DNSRecord dr = *ziter;
254 dr.d_place=DNSResourceRecord::AUTHORITY;
255 records.push_back(dr);
256 }
257 }
258
259 if (!records.empty()) {
260 /* We have found an exact match, we're done */
261 // cerr<<qname<<": exact match in zone '"<<getName()<<"'"<<endl;
262 return result;
263 }
264
265 if (somedata) {
266 /* We have records for that name, but not of the wanted qtype */
267 // cerr<<qname<<": found record in '"<<getName()<<"', but nothing of the right type, sending SOA"<<endl;
268 addSOA(records);
269
270 return result;
271 }
272
273 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
274 DNSName wcarddomain(qname);
275 while(wcarddomain != getName() && wcarddomain.chopOff()) {
276 // cerr<<qname<<": trying '*."<<wcarddomain<<"' in "<<getName()<<endl;
277 range = d_records.equal_range(boost::make_tuple(g_wildcarddnsname + wcarddomain));
278 if (range.first==range.second)
279 continue;
280
281 for(ziter = range.first; ziter != range.second; ++ziter) {
282 DNSRecord dr = *ziter;
283 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
284 if(dr.d_type == qtype || qtype == QType::ANY || dr.d_type == QType::CNAME) {
285 dr.d_name = qname;
286 dr.d_place = DNSResourceRecord::ANSWER;
287 records.push_back(dr);
288 }
289 }
290
291 if (records.empty()) {
292 addSOA(records);
293 }
294
295 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
296 return result;
297 }
298
299 /* Nothing for this name, no wildcard, let's see if there is some NS */
300 DNSName nsdomain(qname);
301 while (nsdomain.chopOff() && nsdomain != getName()) {
302 range = d_records.equal_range(boost::make_tuple(nsdomain,QType::NS));
303 if(range.first == range.second)
304 continue;
305
306 for(ziter = range.first; ziter != range.second; ++ziter) {
307 DNSRecord dr = *ziter;
308 dr.d_place = DNSResourceRecord::AUTHORITY;
309 records.push_back(dr);
310 }
311 }
312
313 if(records.empty()) {
314 // cerr<<qname<<": no NS match in zone '"<<getName()<<"' either, handing out SOA"<<endl;
315 addSOA(records);
316 result = RCode::NXDomain;
317 }
318
319 return result;
320 }
321
322 bool SyncRes::doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res) const
323 {
324 res = domain.getRecords(qname, qtype.getCode(), ret);
325 return true;
326 }
327
328 bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int& res)
329 {
330 string prefix;
331 if(doLog()) {
332 prefix=d_prefix;
333 prefix.append(depth, ' ');
334 }
335
336 DNSName authdomain(qname);
337 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
338 if(iter==t_sstorage.domainmap->end() || !iter->second.isAuth()) {
339 LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
340 return false;
341 }
342
343 LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
344 return doOOBResolve(iter->second, qname, qtype, ret, res);
345 }
346
347 void SyncRes::doEDNSDumpAndClose(int fd)
348 {
349 FILE* fp=fdopen(fd, "w");
350 if (!fp) {
351 return;
352 }
353 fprintf(fp,"IP Address\tMode\tMode last updated at\n");
354 for(const auto& eds : t_sstorage.ednsstatus) {
355 fprintf(fp, "%s\t%d\t%s", eds.first.toString().c_str(), (int)eds.second.mode, ctime(&eds.second.modeSetAt));
356 }
357
358 fclose(fp);
359 }
360
361 uint64_t SyncRes::doDumpNSSpeeds(int fd)
362 {
363 FILE* fp=fdopen(dup(fd), "w");
364 if(!fp)
365 return 0;
366 fprintf(fp, "; nsspeed dump from thread follows\n;\n");
367 uint64_t count=0;
368
369 for(const auto& i : t_sstorage.nsSpeeds)
370 {
371 count++;
372
373 // an <empty> can appear hear in case of authoritative (hosted) zones
374 fprintf(fp, "%s -> ", i.first.toLogString().c_str());
375 for(const auto& j : i.second.d_collection)
376 {
377 // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
378 fprintf(fp, "%s/%f ", j.first.toString().c_str(), j.second.peek());
379 }
380 fprintf(fp, "\n");
381 }
382 fclose(fp);
383 return count;
384 }
385
386 /* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide
387 to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records
388 so that if there are RRSIGs for a name, we'll have them.
389
390 However, some hosts simply can't answer questions which ask for DNSSEC. This can manifest itself as:
391 * No answer
392 * FormErr
393 * Nonsense answer
394
395 The cause of "No answer" may be fragmentation, and it is tempting to probe if smaller answers would get through.
396 Another cause of "No answer" may simply be a network condition.
397 Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
398
399 Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
400 A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
401 clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
402 elsewhere. It may not have happened yet.
403
404 For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
405 */
406
407 int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional<Netmask>& srcmask, LWResult* res) const
408 {
409 /* what is your QUEST?
410 the goal is to get as many remotes as possible on the highest level of EDNS support
411 The levels are:
412
413 0) UNKNOWN Unknown state
414 1) EDNS: Honors EDNS0
415 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
416 3) NOEDNS: Generates FORMERR/NOTIMP on EDNS queries
417
418 Everybody starts out assumed to be '0'.
419 If '0', send out EDNS0
420 If you FORMERR us, go to '3',
421 If no EDNS in response, go to '2'
422 If '1', send out EDNS0
423 If FORMERR, downgrade to 3
424 If '2', keep on including EDNS0, see what happens
425 Same behaviour as 0
426 If '3', send bare queries
427 */
428
429 SyncRes::EDNSStatus* ednsstatus;
430 ednsstatus = &t_sstorage.ednsstatus[ip]; // does this include port? YES
431
432 if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
433 *ednsstatus=SyncRes::EDNSStatus();
434 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
435 }
436
437 SyncRes::EDNSStatus::EDNSMode& mode=ednsstatus->mode;
438 SyncRes::EDNSStatus::EDNSMode oldmode = mode;
439 int EDNSLevel = 0;
440 auto luaconfsLocal = g_luaconfs.getLocal();
441 ResolveContext ctx;
442 #ifdef HAVE_PROTOBUF
443 ctx.d_initialRequestId = d_initialRequestId;
444 #endif
445
446 int ret;
447 for(int tries = 0; tries < 3; ++tries) {
448 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
449
450 if(mode==EDNSStatus::NOEDNS) {
451 g_stats.noEdnsOutQueries++;
452 EDNSLevel = 0; // level != mode
453 }
454 else if(ednsMANDATORY || mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT)
455 EDNSLevel = 1;
456
457 DNSName sendQname(domain);
458 if (g_lowercaseOutgoing)
459 sendQname.makeUsLowerCase();
460
461 if (d_asyncResolve) {
462 ret = d_asyncResolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, luaconfsLocal->outgoingProtobufServer, res);
463 }
464 else {
465 ret=asyncresolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, luaconfsLocal->outgoingProtobufServer, res);
466 }
467 if(ret < 0) {
468 return ret; // transport error, nothing to learn here
469 }
470
471 if(ret == 0) { // timeout, not doing anything with it now
472 return ret;
473 }
474 else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
475 if(res->d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp) {
476 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
477 mode = EDNSStatus::NOEDNS;
478 continue;
479 }
480 else if(!res->d_haveEDNS) {
481 if(mode != EDNSStatus::EDNSIGNORANT) {
482 mode = EDNSStatus::EDNSIGNORANT;
483 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 3"<<endl;
484 }
485 }
486 else {
487 mode = EDNSStatus::EDNSOK;
488 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
489 }
490
491 }
492 if(oldmode != mode || !ednsstatus->modeSetAt)
493 ednsstatus->modeSetAt=d_now.tv_sec;
494 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
495 return ret;
496 }
497 return ret;
498 }
499
500 /*! This function will check the cache and go out to the internet if the answer is not in cache
501 *
502 * \param qname The name we need an answer for
503 * \param qtype
504 * \param ret The vector of DNSRecords we need to fill with the answers
505 * \param depth The recursion depth we are in
506 * \param beenthere
507 * \return DNS RCODE or -1 (Error) or -2 (RPZ hit)
508 */
509 int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state)
510 {
511 string prefix;
512 if(doLog()) {
513 prefix=d_prefix;
514 prefix.append(depth, ' ');
515 }
516
517 LOG(prefix<<qname<<": Wants "<< (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing, "<<(d_requireAuthData ? "" : "NO ")<<"auth data in query for "<<qtype.getName()<<endl);
518
519 state = Indeterminate;
520
521 if(s_maxdepth && depth > s_maxdepth)
522 throw ImmediateServFailException("More than "+std::to_string(s_maxdepth)+" (max-recursion-depth) levels of recursion needed while resolving "+qname.toLogString());
523
524 int res=0;
525
526 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
527 if(!(d_updatingRootNS && qtype.getCode()==QType::NS && qname.isRoot())) {
528 if(d_cacheonly) { // very limited OOB support
529 LWResult lwr;
530 LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
531 DNSName authname(qname);
532 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
533 if(iter != t_sstorage.domainmap->end()) {
534 if(iter->second.isAuth()) {
535 ret.clear();
536 d_wasOutOfBand = doOOBResolve(qname, qtype, ret, depth, res);
537 return res;
538 }
539 else {
540 const vector<ComboAddress>& servers = iter->second.d_servers;
541 const ComboAddress remoteIP = servers.front();
542 LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
543
544 boost::optional<Netmask> nm;
545 res=asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(), false, false, &d_now, nm, &lwr);
546
547 d_totUsec += lwr.d_usec;
548 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
549
550 // filter out the good stuff from lwr.result()
551 if (res == 1) {
552 for(const auto& rec : lwr.d_records) {
553 if(rec.d_place == DNSResourceRecord::ANSWER)
554 ret.push_back(rec);
555 }
556 return 0;
557 }
558 else {
559 return RCode::ServFail;
560 }
561 }
562 }
563 }
564
565 DNSName authname(qname);
566 bool wasForwardedOrAuthZone = false;
567 bool wasAuthZone = false;
568 domainmap_t::const_iterator iter = getBestAuthZone(&authname);
569 if(iter != t_sstorage.domainmap->end()) {
570 wasForwardedOrAuthZone = true;
571 const vector<ComboAddress>& servers = iter->second.d_servers;
572 if(servers.empty()) {
573 wasAuthZone = true;
574 }
575 }
576
577 if(!d_skipCNAMECheck && doCNAMECacheCheck(qname, qtype, ret, depth, res, state, wasAuthZone)) { // will reroute us if needed
578 d_wasOutOfBand = wasAuthZone;
579 return res;
580 }
581
582 if(doCacheCheck(qname, authname, wasForwardedOrAuthZone, wasAuthZone, qtype, ret, depth, res, state)) {
583 // we done
584 d_wasOutOfBand = wasAuthZone;
585 return res;
586 }
587 }
588
589 if(d_cacheonly)
590 return 0;
591
592 LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
593
594 DNSName subdomain(qname);
595 if(qtype == QType::DS) subdomain.chopOff();
596
597 NsSet nsset;
598 bool flawedNSSet=false;
599
600 /* we use subdomain here instead of qname because for DS queries we only care about the state of the parent zone */
601 computeZoneCuts(subdomain, g_rootdnsname, depth);
602
603 // the two retries allow getBestNSNamesFromCache&co to reprime the root
604 // hints, in case they ever go missing
605 for(int tries=0;tries<2 && nsset.empty();++tries) {
606 subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
607 }
608
609 state = getValidationStatus(qname, false);
610
611 LOG(prefix<<qname<<": initial validation status for "<<qname<<" is "<<vStates[state]<<endl);
612
613 if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state)))
614 return 0;
615
616 LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
617
618 if (res == -2)
619 return res;
620
621 return res<0 ? RCode::ServFail : res;
622 }
623
624 #if 0
625 // for testing purposes
626 static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
627 {
628 return !(a.sin4.sin_family < a.sin4.sin_family);
629 }
630 #endif
631
632 struct speedOrderCA
633 {
634 speedOrderCA(std::map<ComboAddress,double>& speeds): d_speeds(speeds) {}
635 bool operator()(const ComboAddress& a, const ComboAddress& b) const
636 {
637 return d_speeds[a] < d_speeds[b];
638 }
639 std::map<ComboAddress, double>& d_speeds;
640 };
641
642 /** This function explicitly goes out for A or AAAA addresses
643 */
644 vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere, bool cacheOnly)
645 {
646 typedef vector<DNSRecord> res_t;
647 res_t res;
648
649 typedef vector<ComboAddress> ret_t;
650 ret_t ret;
651
652 QType type;
653 bool oldCacheOnly = d_cacheonly;
654 bool oldRequireAuthData = d_requireAuthData;
655 bool oldValidationRequested = d_DNSSECValidationRequested;
656 d_requireAuthData = false;
657 d_DNSSECValidationRequested = false;
658 d_cacheonly = cacheOnly;
659
660 for(int j=1; j<2+s_doIPv6; j++)
661 {
662 bool done=false;
663 switch(j) {
664 case 0:
665 type = QType::ANY;
666 break;
667 case 1:
668 type = QType::A;
669 break;
670 case 2:
671 type = QType::AAAA;
672 break;
673 }
674
675 vState newState = Indeterminate;
676 if(!doResolve(qname, type, res,depth+1, beenthere, newState) && !res.empty()) { // this consults cache, OR goes out
677 for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
678 if(i->d_type == QType::A || i->d_type == QType::AAAA) {
679 if(auto rec = getRR<ARecordContent>(*i))
680 ret.push_back(rec->getCA(53));
681 else if(auto aaaarec = getRR<AAAARecordContent>(*i))
682 ret.push_back(aaaarec->getCA(53));
683 done=true;
684 }
685 }
686 }
687 if(done) {
688 if(j==1 && s_doIPv6) { // we got an A record, see if we have some AAAA lying around
689 vector<DNSRecord> cset;
690 if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), false, &cset, d_incomingECSFound ? d_incomingECSNetwork : d_requestor) > 0) {
691 for(auto k=cset.cbegin();k!=cset.cend();++k) {
692 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
693 if (auto drc = getRR<AAAARecordContent>(*k)) {
694 ComboAddress ca=drc->getCA(53);
695 ret.push_back(ca);
696 }
697 }
698 }
699 }
700 }
701 break;
702 }
703 }
704
705 d_requireAuthData = oldRequireAuthData;
706 d_DNSSECValidationRequested = oldValidationRequested;
707 d_cacheonly = oldCacheOnly;
708
709 /* we need to remove from the nsSpeeds collection the existing IPs
710 for this nameserver that are no longer in the set, even if there
711 is only one or none at all in the current set.
712 */
713 map<ComboAddress, double> speeds;
714 auto& collection = t_sstorage.nsSpeeds[qname].d_collection;
715 for(const auto& val: ret) {
716 speeds[val] = collection[val].get(&d_now);
717 }
718
719 t_sstorage.nsSpeeds[qname].purge(speeds);
720
721 if(ret.size() > 1) {
722 random_shuffle(ret.begin(), ret.end(), dns_random);
723 speedOrderCA so(speeds);
724 stable_sort(ret.begin(), ret.end(), so);
725
726 if(doLog()) {
727 string prefix=d_prefix;
728 prefix.append(depth, ' ');
729 LOG(prefix<<"Nameserver "<<qname<<" IPs: ");
730 bool first = true;
731 for(const auto& addr : ret) {
732 if (first) {
733 first = false;
734 }
735 else {
736 LOG(", ");
737 }
738 LOG((addr.toString())<<"(" << (boost::format("%0.2f") % (speeds[addr]/1000.0)).str() <<"ms)");
739 }
740 LOG(endl);
741 }
742 }
743
744 return ret;
745 }
746
747 void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere)
748 {
749 string prefix;
750 DNSName subdomain(qname);
751 if(doLog()) {
752 prefix=d_prefix;
753 prefix.append(depth, ' ');
754 }
755 bestns.clear();
756 bool brokeloop;
757 do {
758 brokeloop=false;
759 LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
760 vector<DNSRecord> ns;
761 *flawedNSSet = false;
762
763 if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), false, &ns, d_incomingECSFound ? d_incomingECSNetwork : d_requestor) > 0) {
764 for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
765 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
766 vector<DNSRecord> aset;
767
768 const DNSRecord& dr=*k;
769 auto nrr = getRR<NSRecordContent>(dr);
770 if(nrr && (!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
771 false, doLog() ? &aset : 0, d_incomingECSFound ? d_incomingECSNetwork : d_requestor) > 5)) {
772 bestns.push_back(dr);
773 LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<nrr->getNS()<<"'"<<endl);
774 LOG(prefix<<qname<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
775 if(!aset.empty()) {
776 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
777 }
778 else {
779 LOG(", not in cache / did not look at cache"<<endl);
780 }
781 }
782 else {
783 *flawedNSSet=true;
784 LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
785 }
786 }
787 }
788
789 if(!bestns.empty()) {
790 GetBestNSAnswer answer;
791 answer.qname=qname;
792 answer.qtype=qtype.getCode();
793 for(const auto& dr : bestns) {
794 if (auto nsContent = getRR<NSRecordContent>(dr)) {
795 answer.bestns.insert(make_pair(dr.d_name, nsContent->getNS()));
796 }
797 }
798
799 if(beenthere.count(answer)) {
800 brokeloop=true;
801 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
802 ;
803 if(doLog())
804 for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
805 bool neo = !(*j< answer || answer<*j);
806 LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
807 }
808 bestns.clear();
809 }
810 else {
811 beenthere.insert(answer);
812 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
813 return;
814 }
815 }
816 }
817 LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
818
819 if(subdomain.isRoot() && !brokeloop) {
820 // We lost the root NS records
821 primeHints();
822 LOG(prefix<<qname<<": reprimed the root"<<endl);
823 /* let's prevent an infinite loop */
824 if (!d_updatingRootNS) {
825 getRootNS(d_now, d_asyncResolve);
826 }
827 }
828 } while(subdomain.chopOff());
829 }
830
831 SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) const
832 {
833 SyncRes::domainmap_t::const_iterator ret;
834 do {
835 ret=t_sstorage.domainmap->find(*qname);
836 if(ret!=t_sstorage.domainmap->end())
837 break;
838 }while(qname->chopOff());
839 return ret;
840 }
841
842 /** doesn't actually do the work, leaves that to getBestNSFromCache */
843 DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere)
844 {
845 DNSName subdomain(qname);
846 DNSName authdomain(qname);
847
848 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
849 if(iter!=t_sstorage.domainmap->end()) {
850 if( iter->second.isAuth() )
851 // this gets picked up in doResolveAt, the empty DNSName, combined with the
852 // empty vector means 'we are auth for this zone'
853 nsset.insert({DNSName(), {{}, false}});
854 else {
855 // Again, picked up in doResolveAt. An empty DNSName, combined with a
856 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
857 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
858 nsset.insert({DNSName(), {iter->second.d_servers, iter->second.shouldRecurse() }});
859 }
860 return authdomain;
861 }
862
863 vector<DNSRecord> bestns;
864 getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
865
866 for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) {
867 // The actual resolver code will not even look at the ComboAddress or bool
868 const auto nsContent = getRR<NSRecordContent>(*k);
869 if (nsContent) {
870 nsset.insert({nsContent->getNS(), {{}, false}});
871 if(k==bestns.cbegin())
872 subdomain=k->d_name;
873 }
874 }
875 return subdomain;
876 }
877
878 bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res, vState& state, bool wasAuthZone)
879 {
880 string prefix;
881 if(doLog()) {
882 prefix=d_prefix;
883 prefix.append(depth, ' ');
884 }
885
886 if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
887 LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
888 res=RCode::ServFail;
889 return true;
890 }
891
892 LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<qname<<"|CNAME"<<"'"<<endl);
893 vector<DNSRecord> cset;
894 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
895 vector<std::shared_ptr<DNSRecord>> authorityRecs;
896 bool wasAuth;
897 if(t_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), d_requireAuthData, &cset, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth) > 0) {
898
899 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
900 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
901
902 if (!wasAuthZone && shouldValidate() && wasAuth && state == Indeterminate && d_requireAuthData) {
903 /* This means we couldn't figure out the state when this entry was cached,
904 most likely because we hadn't computed the zone cuts yet. */
905 /* make sure they are computed before validating */
906 DNSName subdomain(qname);
907 /* if we are retrieving a DS, we only care about the state of the parent zone */
908 if(qtype == QType::DS)
909 subdomain.chopOff();
910
911 computeZoneCuts(subdomain, g_rootdnsname, depth);
912
913 vState recordState = getValidationStatus(qname, false);
914 if (recordState == Secure) {
915 LOG(prefix<<qname<<": got Indeterminate state from the CNAME cache, validating.."<<endl);
916 state = SyncRes::validateRecordsWithSigs(depth, qname, QType(QType::CNAME), qname, cset, signatures);
917 if (state != Indeterminate) {
918 LOG(prefix<<qname<<": got Indeterminate state from the CNAME cache, new validation result is "<<vStates[state]<<endl);
919 t_RC->updateValidationStatus(d_now.tv_sec, qname, QType(QType::CNAME), d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_requireAuthData, state);
920 }
921 }
922 }
923
924 LOG(prefix<<qname<<": Found cache CNAME hit for '"<< qname << "|CNAME" <<"' to '"<<j->d_content->getZoneRepresentation()<<"', validation state is "<<vStates[state]<<endl);
925
926 DNSRecord dr=*j;
927 dr.d_ttl-=d_now.tv_sec;
928 ret.push_back(dr);
929
930 for(const auto& signature : signatures) {
931 DNSRecord sigdr;
932 sigdr.d_type=QType::RRSIG;
933 sigdr.d_name=qname;
934 sigdr.d_ttl=j->d_ttl - d_now.tv_sec;
935 sigdr.d_content=signature;
936 sigdr.d_place=DNSResourceRecord::ANSWER;
937 sigdr.d_class=QClass::IN;
938 ret.push_back(sigdr);
939 }
940
941 for(const auto& rec : authorityRecs) {
942 DNSRecord authDR(*rec);
943 authDR.d_ttl=j->d_ttl - d_now.tv_sec;
944 ret.push_back(authDR);
945 }
946
947 if(qtype != QType::CNAME) { // perhaps they really wanted a CNAME!
948 set<GetBestNSAnswer>beenthere;
949
950 vState cnameState = Indeterminate;
951 const auto cnameContent = getRR<CNAMERecordContent>(*j);
952 if (cnameContent) {
953 res=doResolve(cnameContent->getTarget(), qtype, ret, depth+1, beenthere, cnameState);
954 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
955 updateValidationState(state, cnameState);
956 }
957 }
958 else
959 res=0;
960
961 return true;
962 }
963 }
964 }
965 LOG(prefix<<qname<<": No CNAME cache hit of '"<< qname << "|CNAME" <<"' found"<<endl);
966 return false;
967 }
968
969 namespace {
970 struct CacheEntry
971 {
972 vector<DNSRecord> records;
973 vector<shared_ptr<RRSIGRecordContent>> signatures;
974 uint32_t signaturesTTL{std::numeric_limits<uint32_t>::max()};
975 };
976 struct CacheKey
977 {
978 DNSName name;
979 uint16_t type;
980 DNSResourceRecord::Place place;
981 bool operator<(const CacheKey& rhs) const {
982 return tie(name, type) < tie(rhs.name, rhs.type);
983 }
984 };
985 typedef map<CacheKey, CacheEntry> tcache_t;
986 }
987
988 static void reapRecordsFromNegCacheEntryForValidation(tcache_t& tcache, const vector<DNSRecord>& records)
989 {
990 for (const auto& rec : records) {
991 if (rec.d_type == QType::RRSIG) {
992 auto rrsig = getRR<RRSIGRecordContent>(rec);
993 if (rrsig) {
994 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
995 }
996 } else {
997 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(rec);
998 }
999 }
1000 }
1001
1002 /*!
1003 * Convience function to push the records from records into ret with a new TTL
1004 *
1005 * \param records DNSRecords that need to go into ret
1006 * \param ttl The new TTL for these records
1007 * \param ret The vector of DNSRecords that should contian the records with the modified TTL
1008 */
1009 static void addTTLModifiedRecords(const vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
1010 for (const auto& rec : records) {
1011 DNSRecord r(rec);
1012 r.d_ttl = ttl;
1013 ret.push_back(r);
1014 }
1015 }
1016
1017 void SyncRes::computeNegCacheValidationStatus(NegCache::NegCacheEntry& ne, const DNSName& qname, const QType& qtype, const int res, vState& state, unsigned int depth)
1018 {
1019 DNSName subdomain(qname);
1020 /* if we are retrieving a DS, we only care about the state of the parent zone */
1021 if(qtype == QType::DS)
1022 subdomain.chopOff();
1023
1024 computeZoneCuts(subdomain, g_rootdnsname, depth);
1025
1026 tcache_t tcache;
1027 reapRecordsFromNegCacheEntryForValidation(tcache, ne.authoritySOA.records);
1028 reapRecordsFromNegCacheEntryForValidation(tcache, ne.authoritySOA.signatures);
1029 reapRecordsFromNegCacheEntryForValidation(tcache, ne.DNSSECRecords.records);
1030 reapRecordsFromNegCacheEntryForValidation(tcache, ne.DNSSECRecords.signatures);
1031
1032 for (const auto& entry : tcache) {
1033 // this happens when we did store signatures, but passed on the records themselves
1034 if (entry.second.records.empty()) {
1035 continue;
1036 }
1037
1038 const DNSName& owner = entry.first.name;
1039
1040 vState recordState = getValidationStatus(owner, false);
1041 if (state == Indeterminate) {
1042 state = recordState;
1043 }
1044
1045 if (recordState == Secure) {
1046 recordState = SyncRes::validateRecordsWithSigs(depth, qname, qtype, owner, entry.second.records, entry.second.signatures);
1047 }
1048
1049 if (recordState != Indeterminate && recordState != state) {
1050 updateValidationState(state, recordState);
1051 if (state != Secure) {
1052 break;
1053 }
1054 }
1055 }
1056
1057 if (state == Secure) {
1058 dState expectedState = res == RCode::NXDomain ? NXDOMAIN : NXQTYPE;
1059 dState denialState = getDenialValidationState(ne, state, expectedState, false);
1060 updateDenialValidationState(ne, state, denialState, expectedState, qtype == QType::DS);
1061 }
1062 if (state != Indeterminate) {
1063 /* validation succeeded, let's update the cache entry so we don't have to validate again */
1064 t_sstorage.negcache.updateValidationStatus(ne.d_name, ne.d_qtype, state);
1065 }
1066 }
1067
1068 bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
1069 {
1070 bool giveNegative=false;
1071
1072 string prefix;
1073 if(doLog()) {
1074 prefix=d_prefix;
1075 prefix.append(depth, ' ');
1076 }
1077
1078 // 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)
1079 DNSName sqname(qname);
1080 QType sqt(qtype);
1081 uint32_t sttl=0;
1082 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
1083 vState cachedState;
1084 NegCache::NegCacheEntry ne;
1085
1086 if(s_rootNXTrust &&
1087 t_sstorage.negcache.getRootNXTrust(qname, d_now, ne) &&
1088 ne.d_auth.isRoot() &&
1089 !(wasForwardedOrAuthZone && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
1090 sttl = ne.d_ttd - d_now.tv_sec;
1091 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' & '"<<ne.d_name<<"' for another "<<sttl<<" seconds"<<endl);
1092 res = RCode::NXDomain;
1093 giveNegative = true;
1094 cachedState = ne.d_validationState;
1095 }
1096 else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) &&
1097 !(wasForwardedOrAuthZone && ne.d_auth != authname)) { // Only the authname nameserver can neg cache entries
1098
1099 /* If we are looking for a DS, discard NXD if auth == qname
1100 and ask for a specific denial instead */
1101 if (qtype != QType::DS || ne.d_qtype.getCode() || ne.d_auth != qname ||
1102 t_sstorage.negcache.get(qname, qtype, d_now, ne, true))
1103 {
1104 res = 0;
1105 sttl = ne.d_ttd - d_now.tv_sec;
1106 giveNegative = true;
1107 cachedState = ne.d_validationState;
1108 if(ne.d_qtype.getCode()) {
1109 LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
1110 res = RCode::NoError;
1111 }
1112 else {
1113 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
1114 res = RCode::NXDomain;
1115 }
1116 }
1117 }
1118
1119 if (giveNegative) {
1120
1121 state = cachedState;
1122
1123 if (!wasAuthZone && shouldValidate() && state == Indeterminate) {
1124 LOG(prefix<<qname<<": got Indeterminate state for records retrieved from the negative cache, validating.."<<endl);
1125 computeNegCacheValidationStatus(ne, qname, qtype, res, state, depth);
1126 }
1127
1128 // Transplant SOA to the returned packet
1129 addTTLModifiedRecords(ne.authoritySOA.records, sttl, ret);
1130 if(d_doDNSSEC) {
1131 addTTLModifiedRecords(ne.authoritySOA.signatures, sttl, ret);
1132 addTTLModifiedRecords(ne.DNSSECRecords.records, sttl, ret);
1133 addTTLModifiedRecords(ne.DNSSECRecords.signatures, sttl, ret);
1134 }
1135
1136 LOG(prefix<<qname<<": updating validation state with negative cache content for "<<qname<<" to "<<vStates[state]<<endl);
1137 return true;
1138 }
1139
1140 vector<DNSRecord> cset;
1141 bool found=false, expired=false;
1142 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
1143 vector<std::shared_ptr<DNSRecord>> authorityRecs;
1144 uint32_t ttl=0;
1145 bool wasCachedAuth;
1146 if(t_RC->get(d_now.tv_sec, sqname, sqt, d_requireAuthData, &cset, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth) > 0) {
1147
1148 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
1149
1150 if (!wasAuthZone && shouldValidate() && wasCachedAuth && cachedState == Indeterminate && d_requireAuthData) {
1151
1152 /* This means we couldn't figure out the state when this entry was cached,
1153 most likely because we hadn't computed the zone cuts yet. */
1154 /* make sure they are computed before validating */
1155 DNSName subdomain(sqname);
1156 /* if we are retrieving a DS, we only care about the state of the parent zone */
1157 if(qtype == QType::DS)
1158 subdomain.chopOff();
1159
1160 computeZoneCuts(subdomain, g_rootdnsname, depth);
1161
1162 vState recordState = getValidationStatus(qname, false);
1163 if (recordState == Secure) {
1164 LOG(prefix<<sqname<<": got Indeterminate state from the cache, validating.."<<endl);
1165 cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures);
1166 }
1167 else {
1168 cachedState = recordState;
1169 }
1170
1171 if (cachedState != Indeterminate) {
1172 LOG(prefix<<qname<<": got Indeterminate state from the cache, validation result is "<<vStates[cachedState]<<endl);
1173 t_RC->updateValidationStatus(d_now.tv_sec, sqname, sqt, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_requireAuthData, cachedState);
1174 }
1175 }
1176
1177 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
1178 LOG(j->d_content->getZoneRepresentation());
1179 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
1180 DNSRecord dr=*j;
1181 ttl = (dr.d_ttl-=d_now.tv_sec);
1182 ret.push_back(dr);
1183 LOG("[ttl="<<dr.d_ttl<<"] ");
1184 found=true;
1185 }
1186 else {
1187 LOG("[expired] ");
1188 expired=true;
1189 }
1190 }
1191
1192 for(const auto& signature : signatures) {
1193 DNSRecord dr;
1194 dr.d_type=QType::RRSIG;
1195 dr.d_name=sqname;
1196 dr.d_ttl=ttl;
1197 dr.d_content=signature;
1198 dr.d_place = DNSResourceRecord::ANSWER;
1199 dr.d_class=QClass::IN;
1200 ret.push_back(dr);
1201 }
1202
1203 for(const auto& rec : authorityRecs) {
1204 DNSRecord dr(*rec);
1205 dr.d_ttl=ttl;
1206 ret.push_back(dr);
1207 }
1208
1209 LOG(endl);
1210 if(found && !expired) {
1211 if (!giveNegative)
1212 res=0;
1213 LOG(prefix<<qname<<": updating validation state with cache content for "<<qname<<" to "<<vStates[cachedState]<<endl);
1214 state = cachedState;
1215 return true;
1216 }
1217 else
1218 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
1219 }
1220
1221 return false;
1222 }
1223
1224 bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
1225 {
1226 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
1227 }
1228
1229 struct speedOrder
1230 {
1231 speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
1232 bool operator()(const DNSName &a, const DNSName &b) const
1233 {
1234 return d_speeds[a] < d_speeds[b];
1235 }
1236 map<DNSName, double>& d_speeds;
1237 };
1238
1239 inline vector<DNSName> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
1240 {
1241 vector<DNSName> rnameservers;
1242 rnameservers.reserve(tnameservers.size());
1243 for(const auto& tns: tnameservers) {
1244 rnameservers.push_back(tns.first);
1245 if(tns.first.empty()) // this was an authoritative OOB zone, don't pollute the nsSpeeds with that
1246 return rnameservers;
1247 }
1248 map<DNSName, double> speeds;
1249
1250 for(const auto& val: rnameservers) {
1251 double speed;
1252 speed=t_sstorage.nsSpeeds[val].get(&d_now);
1253 speeds[val]=speed;
1254 }
1255 random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
1256 speedOrder so(speeds);
1257 stable_sort(rnameservers.begin(),rnameservers.end(), so);
1258
1259 if(doLog()) {
1260 LOG(prefix<<"Nameservers: ");
1261 for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
1262 if(i!=rnameservers.begin()) {
1263 LOG(", ");
1264 if(!((i-rnameservers.begin())%3)) {
1265 LOG(endl<<prefix<<" ");
1266 }
1267 }
1268 LOG((i->empty() ? string("<empty>") : i->toString())<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
1269 }
1270 LOG(endl);
1271 }
1272 return rnameservers;
1273 }
1274
1275 static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<RRSIGRecordContent>& rrsig)
1276 {
1277 uint32_t res = 0;
1278 if (now < rrsig->d_sigexpire) {
1279 res = static_cast<uint32_t>(rrsig->d_sigexpire) - now;
1280 }
1281 return res;
1282 }
1283
1284 static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
1285
1286 /* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1287 *
1288 * \param records The records to parse for the authority SOA and NSEC(3) records
1289 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1290 */
1291 static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne, const time_t now, uint32_t* lowestTTL) {
1292 for(const auto& rec : records) {
1293 if(rec.d_place != DNSResourceRecord::AUTHORITY)
1294 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1295 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1296 // records MUST be in the same section as the records they cover.
1297 // Hence, we ignore all records outside of the AUTHORITY section.
1298 continue;
1299
1300 if(rec.d_type == QType::RRSIG) {
1301 auto rrsig = getRR<RRSIGRecordContent>(rec);
1302 if(rrsig) {
1303 if(rrsig->d_type == QType::SOA) {
1304 ne.authoritySOA.signatures.push_back(rec);
1305 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1306 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1307 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1308 }
1309 }
1310 if(nsecTypes.count(rrsig->d_type)) {
1311 ne.DNSSECRecords.signatures.push_back(rec);
1312 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1313 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1314 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1315 }
1316 }
1317 }
1318 continue;
1319 }
1320 if(rec.d_type == QType::SOA) {
1321 ne.authoritySOA.records.push_back(rec);
1322 if (lowestTTL) {
1323 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1324 }
1325 continue;
1326 }
1327 if(nsecTypes.count(rec.d_type)) {
1328 ne.DNSSECRecords.records.push_back(rec);
1329 if (lowestTTL) {
1330 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1331 }
1332 continue;
1333 }
1334 }
1335 }
1336
1337 static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
1338 {
1339 cspmap_t cspmap;
1340 for(const auto& rec : ne.DNSSECRecords.signatures) {
1341 if(rec.d_type == QType::RRSIG) {
1342 auto rrc = getRR<RRSIGRecordContent>(rec);
1343 if (rrc) {
1344 cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
1345 }
1346 }
1347 }
1348 for(const auto& rec : ne.DNSSECRecords.records) {
1349 cspmap[{rec.d_name, rec.d_type}].records.push_back(rec.d_content);
1350 }
1351 return cspmap;
1352 }
1353
1354 // TODO remove after processRecords is fixed!
1355 // Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
1356 static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1357 {
1358 NegCache::NegCacheEntry ne;
1359 harvestNXRecords(records, ne, 0, nullptr);
1360 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
1361 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
1362 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
1363 }
1364
1365 bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
1366 {
1367 if(d_wantsRPZ) {
1368 for (auto const &ns : nameservers) {
1369 d_appliedPolicy = dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
1370 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1371 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1372 return true;
1373 }
1374
1375 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1376 for (auto const &address : ns.second.first) {
1377 d_appliedPolicy = dfe.getProcessingPolicy(address, d_discardedPolicies);
1378 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1379 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1380 return true;
1381 }
1382 }
1383 }
1384 }
1385 return false;
1386 }
1387
1388 bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
1389 {
1390 if (d_wantsRPZ) {
1391 d_appliedPolicy = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies);
1392 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
1393 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
1394 return true;
1395 }
1396 }
1397 return false;
1398 }
1399
1400 vector<ComboAddress> SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector<DNSName >::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<DNSName >& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly)
1401 {
1402 vector<ComboAddress> result;
1403
1404 if(!tns->empty()) {
1405 LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
1406 result = getAddrs(*tns, depth+2, beenthere, cacheOnly);
1407 pierceDontQuery=false;
1408 }
1409 else {
1410 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
1411
1412 result = nameservers[*tns].first;
1413 if(result.size() > 1) {
1414 LOG("s");
1415 }
1416 LOG(endl);
1417
1418 sendRDQuery = nameservers[*tns].second;
1419 pierceDontQuery=true;
1420 }
1421 return result;
1422 }
1423
1424 bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1425 {
1426 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
1427 LOG(prefix<<qname<<": server throttled "<<endl);
1428 s_throttledqueries++; d_throttledqueries++;
1429 return true;
1430 }
1431 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
1432 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
1433 s_throttledqueries++; d_throttledqueries++;
1434 return true;
1435 }
1436 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
1437 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
1438 s_dontqueries++;
1439 return true;
1440 }
1441 return false;
1442 }
1443
1444 bool SyncRes::validationEnabled() const
1445 {
1446 return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
1447 }
1448
1449 uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const
1450 {
1451 uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
1452 for(const auto& record : records)
1453 lowestTTD = min(lowestTTD, record.d_ttl);
1454
1455 /* even if it was not requested for that request (Process, and neither AD nor DO set),
1456 it might be requested at a later time so we need to be careful with the TTL. */
1457 if (validationEnabled() && !signatures.empty()) {
1458 /* if we are validating, we don't want to cache records after their signatures expire. */
1459 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
1460 lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
1461
1462 for(const auto& sig : signatures) {
1463 if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
1464 // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
1465 lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
1466 }
1467 }
1468 }
1469
1470 return lowestTTD;
1471 }
1472
1473 void SyncRes::updateValidationState(vState& state, const vState stateUpdate)
1474 {
1475 LOG(d_prefix<<"validation state was "<<std::string(vStates[state])<<", state update is "<<std::string(vStates[stateUpdate]));
1476
1477 if (stateUpdate == TA) {
1478 state = Secure;
1479 }
1480 else if (stateUpdate == NTA) {
1481 state = Insecure;
1482 }
1483 else if (stateUpdate == Bogus) {
1484 state = Bogus;
1485 }
1486 else if (state == Indeterminate) {
1487 state = stateUpdate;
1488 }
1489 else if (stateUpdate == Insecure) {
1490 if (state != Bogus) {
1491 state = Insecure;
1492 }
1493 }
1494 LOG(", validation state is now "<<std::string(vStates[state])<<endl);
1495 }
1496
1497 vState SyncRes::getTA(const DNSName& zone, dsmap_t& ds)
1498 {
1499 auto luaLocal = g_luaconfs.getLocal();
1500
1501 if (luaLocal->dsAnchors.empty()) {
1502 LOG(d_prefix<<": No trust anchors configured, everything is Insecure"<<endl);
1503 /* We have no TA, everything is insecure */
1504 return Insecure;
1505 }
1506
1507 std::string reason;
1508 if (haveNegativeTrustAnchor(luaLocal->negAnchors, zone, reason)) {
1509 LOG(d_prefix<<": got NTA for '"<<zone<<"'"<<endl);
1510 return NTA;
1511 }
1512
1513 if (getTrustAnchor(luaLocal->dsAnchors, zone, ds)) {
1514 LOG(d_prefix<<": got TA for '"<<zone<<"'"<<endl);
1515 return TA;
1516 }
1517 else {
1518 LOG(d_prefix<<": no TA found for '"<<zone<<"' among "<< luaLocal->dsAnchors.size()<<endl);
1519 }
1520
1521 if (zone.isRoot()) {
1522 /* No TA for the root */
1523 return Insecure;
1524 }
1525
1526 return Indeterminate;
1527 }
1528
1529 static size_t countSupportedDS(const dsmap_t& dsmap)
1530 {
1531 size_t count = 0;
1532
1533 for (const auto& ds : dsmap) {
1534 if (isSupportedDS(ds)) {
1535 count++;
1536 }
1537 }
1538
1539 return count;
1540 }
1541
1542 vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsigned int depth, bool bogusOnNXD, bool* foundCut)
1543 {
1544 vState result = getTA(zone, ds);
1545
1546 if (result != Indeterminate || taOnly) {
1547 if (foundCut) {
1548 *foundCut = (result != Indeterminate);
1549 }
1550
1551 if (result == TA) {
1552 if (countSupportedDS(ds) == 0) {
1553 ds.clear();
1554 result = Insecure;
1555 }
1556 else {
1557 result = Secure;
1558 }
1559 }
1560 else if (result == NTA) {
1561 result = Insecure;
1562 }
1563
1564 return result;
1565 }
1566
1567 bool oldSkipCNAME = d_skipCNAMECheck;
1568 d_skipCNAMECheck = true;
1569
1570 std::set<GetBestNSAnswer> beenthere;
1571 std::vector<DNSRecord> dsrecords;
1572
1573 vState state = Indeterminate;
1574 int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state);
1575 d_skipCNAMECheck = oldSkipCNAME;
1576
1577 if (rcode == RCode::NoError || (rcode == RCode::NXDomain && !bogusOnNXD)) {
1578
1579 uint8_t bestDigestType = 0;
1580
1581 if (state == Secure) {
1582 bool gotCNAME = false;
1583 for (const auto& record : dsrecords) {
1584 if (record.d_type == QType::DS) {
1585 const auto dscontent = getRR<DSRecordContent>(record);
1586 if (dscontent && isSupportedDS(*dscontent)) {
1587 // Make GOST a lower prio than SHA256
1588 if (dscontent->d_digesttype == DNSSECKeeper::GOST && bestDigestType == DNSSECKeeper::SHA256) {
1589 continue;
1590 }
1591 if (dscontent->d_digesttype > bestDigestType || (bestDigestType == DNSSECKeeper::GOST && dscontent->d_digesttype == DNSSECKeeper::SHA256)) {
1592 bestDigestType = dscontent->d_digesttype;
1593 }
1594 ds.insert(*dscontent);
1595 }
1596 }
1597 else if (record.d_type == QType::CNAME && record.d_name == zone) {
1598 gotCNAME = true;
1599 }
1600 }
1601
1602 /* RFC 4509 section 3: "Validator implementations SHOULD ignore DS RRs containing SHA-1
1603 * digests if DS RRs with SHA-256 digests are present in the DS RRset."
1604 * As SHA348 is specified as well, the spirit of the this line is "use the best algorithm".
1605 */
1606 for (auto dsrec = ds.begin(); dsrec != ds.end(); ) {
1607 if (dsrec->d_digesttype != bestDigestType) {
1608 dsrec = ds.erase(dsrec);
1609 }
1610 else {
1611 ++dsrec;
1612 }
1613 }
1614
1615 if (rcode == RCode::NoError && ds.empty()) {
1616 if (foundCut) {
1617 if (gotCNAME || denialProvesNoDelegation(zone, dsrecords)) {
1618 /* we are still inside the same Secure zone */
1619
1620 *foundCut = false;
1621 return Secure;
1622 }
1623
1624 *foundCut = true;
1625 }
1626
1627 return Insecure;
1628 } else if (foundCut && rcode == RCode::NoError && !ds.empty()) {
1629 *foundCut = true;
1630 }
1631 }
1632
1633 return state;
1634 }
1635
1636 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1637 return Bogus;
1638 }
1639
1640 bool SyncRes::haveExactValidationStatus(const DNSName& domain)
1641 {
1642 if (!shouldValidate()) {
1643 return false;
1644 }
1645 const auto& it = d_cutStates.find(domain);
1646 if (it != d_cutStates.cend()) {
1647 return true;
1648 }
1649 return false;
1650 }
1651
1652 vState SyncRes::getValidationStatus(const DNSName& subdomain, bool allowIndeterminate)
1653 {
1654 vState result = Indeterminate;
1655
1656 if (!shouldValidate()) {
1657 return result;
1658 }
1659 DNSName name(subdomain);
1660 do {
1661 const auto& it = d_cutStates.find(name);
1662 if (it != d_cutStates.cend()) {
1663 if (allowIndeterminate || it->second != Indeterminate) {
1664 LOG(d_prefix<<": got status "<<vStates[it->second]<<" for name "<<subdomain<<" (from "<<name<<")"<<endl);
1665 return it->second;
1666 }
1667 }
1668 }
1669 while (name.chopOff());
1670
1671 return result;
1672 }
1673
1674 bool SyncRes::lookForCut(const DNSName& qname, unsigned int depth, const vState existingState, vState& newState)
1675 {
1676 bool foundCut = false;
1677 dsmap_t ds;
1678 vState dsState = getDSRecords(qname, ds, newState == Bogus || existingState == Insecure || existingState == Bogus, depth, false, &foundCut);
1679
1680 if (dsState != Indeterminate) {
1681 newState = dsState;
1682 }
1683
1684 return foundCut;
1685 }
1686
1687 void SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth)
1688 {
1689 if(!begin.isPartOf(end)) {
1690 LOG(d_prefix<<" "<<begin.toLogString()<<" is not part of "<<end.toString()<<endl);
1691 throw PDNSException(begin.toLogString() + " is not part of " + end.toString());
1692 }
1693
1694 if (d_cutStates.count(begin) != 0) {
1695 return;
1696 }
1697
1698 dsmap_t ds;
1699 vState cutState = getDSRecords(end, ds, false, depth);
1700 LOG(d_prefix<<": setting cut state for "<<end<<" to "<<vStates[cutState]<<endl);
1701 d_cutStates[end] = cutState;
1702
1703 if (!shouldValidate()) {
1704 return;
1705 }
1706
1707 DNSName qname(end);
1708 std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
1709
1710 bool oldSkipCNAME = d_skipCNAMECheck;
1711 d_skipCNAMECheck = true;
1712
1713 while(qname != begin) {
1714 if (labelsToAdd.empty())
1715 break;
1716
1717 qname.prependRawLabel(labelsToAdd.back());
1718 labelsToAdd.pop_back();
1719 LOG(d_prefix<<": - Looking for a cut at "<<qname<<endl);
1720
1721 const auto cutIt = d_cutStates.find(qname);
1722 if (cutIt != d_cutStates.cend()) {
1723 if (cutIt->second != Indeterminate) {
1724 LOG(d_prefix<<": - Cut already known at "<<qname<<endl);
1725 cutState = cutIt->second;
1726 continue;
1727 }
1728 }
1729
1730 /* no need to look for NS and DS if we are already insecure or bogus,
1731 just look for (N)TA
1732 */
1733 if (cutState == Insecure || cutState == Bogus) {
1734 dsmap_t cutDS;
1735 vState newState = getDSRecords(qname, cutDS, true, depth);
1736 if (newState == Indeterminate) {
1737 continue;
1738 }
1739
1740 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[newState]<<endl);
1741 cutState = newState;
1742
1743 d_cutStates[qname] = cutState;
1744
1745 continue;
1746 }
1747
1748 vState newState = Indeterminate;
1749 /* temporarily mark as Indeterminate, so that we won't enter an endless loop
1750 trying to determine that zone cut again. */
1751 d_cutStates[qname] = newState;
1752 bool foundCut = lookForCut(qname, depth + 1, cutState, newState);
1753 if (foundCut) {
1754 LOG(d_prefix<<": - Found cut at "<<qname<<endl);
1755 if (newState != Indeterminate) {
1756 cutState = newState;
1757 }
1758 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[cutState]<<endl);
1759 d_cutStates[qname] = cutState;
1760 }
1761 else {
1762 /* remove the temporary cut */
1763 LOG(d_prefix<<qname<<": removing cut state for "<<qname<<endl);
1764 d_cutStates.erase(qname);
1765 }
1766 }
1767
1768 d_skipCNAMECheck = oldSkipCNAME;
1769
1770 LOG(d_prefix<<": list of cuts from "<<begin<<" to "<<end<<endl);
1771 for (const auto& cut : d_cutStates) {
1772 if (cut.first.isRoot() || (begin.isPartOf(cut.first) && cut.first.isPartOf(end))) {
1773 LOG(" - "<<cut.first<<": "<<vStates[cut.second]<<endl);
1774 }
1775 }
1776 }
1777
1778 vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth)
1779 {
1780 dsmap_t ds;
1781 if (!signatures.empty()) {
1782 DNSName signer = getSigner(signatures);
1783
1784 if (!signer.empty() && zone.isPartOf(signer)) {
1785 vState state = getDSRecords(signer, ds, false, depth);
1786
1787 if (state != Secure) {
1788 return state;
1789 }
1790 }
1791 }
1792
1793 skeyset_t tentativeKeys;
1794 std::vector<shared_ptr<DNSRecordContent> > toSign;
1795
1796 for (const auto& dnskey : dnskeys) {
1797 if (dnskey.d_type == QType::DNSKEY) {
1798 auto content = getRR<DNSKEYRecordContent>(dnskey);
1799 if (content) {
1800 tentativeKeys.insert(content);
1801 toSign.push_back(content);
1802 }
1803 }
1804 }
1805
1806 LOG(d_prefix<<": trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
1807 skeyset_t validatedKeys;
1808 validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
1809
1810 LOG(d_prefix<<": we now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
1811
1812 /* if we found at least one valid RRSIG covering the set,
1813 all tentative keys are validated keys. Otherwise it means
1814 we haven't found at least one DNSKEY and a matching RRSIG
1815 covering this set, this looks Bogus. */
1816 if (validatedKeys.size() != tentativeKeys.size()) {
1817 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1818 return Bogus;
1819 }
1820
1821 return Secure;
1822 }
1823
1824 vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth)
1825 {
1826 std::vector<DNSRecord> records;
1827 std::set<GetBestNSAnswer> beenthere;
1828 LOG(d_prefix<<"Retrieving DNSKeys for "<<signer<<endl);
1829
1830 vState state = Indeterminate;
1831 /* following CNAME might lead to us to the wrong DNSKEY */
1832 bool oldSkipCNAME = d_skipCNAMECheck;
1833 d_skipCNAMECheck = true;
1834 int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state);
1835 d_skipCNAMECheck = oldSkipCNAME;
1836
1837 if (rcode == RCode::NoError) {
1838 if (state == Secure) {
1839 for (const auto& key : records) {
1840 if (key.d_type == QType::DNSKEY) {
1841 auto content = getRR<DNSKEYRecordContent>(key);
1842 if (content) {
1843 keys.insert(content);
1844 }
1845 }
1846 }
1847 }
1848 LOG(d_prefix<<"Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<vStates[state]<<endl);
1849 return state;
1850 }
1851
1852 LOG(d_prefix<<"Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
1853 return Bogus;
1854 }
1855
1856 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)
1857 {
1858 skeyset_t keys;
1859 if (!signatures.empty()) {
1860 const DNSName signer = getSigner(signatures);
1861 if (!signer.empty() && name.isPartOf(signer)) {
1862 if ((qtype == QType::DNSKEY || qtype == QType::DS) && signer == qname) {
1863 /* we are already retrieving those keys, sorry */
1864 return Indeterminate;
1865 }
1866 vState state = getDNSKeys(signer, keys, depth);
1867 if (state != Secure) {
1868 return state;
1869 }
1870 }
1871 } else {
1872 LOG(d_prefix<<"Bogus!"<<endl);
1873 return Bogus;
1874 }
1875
1876 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
1877 for (const auto& record : records) {
1878 recordcontents.push_back(record.d_content);
1879 }
1880
1881 LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
1882 if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
1883 LOG(d_prefix<<"Secure!"<<endl);
1884 return Secure;
1885 }
1886
1887 LOG(d_prefix<<"Bogus!"<<endl);
1888 return Bogus;
1889 }
1890
1891 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, unsigned int& wildcardLabelsCount)
1892 {
1893 tcache_t tcache;
1894
1895 string prefix;
1896 if(doLog()) {
1897 prefix=d_prefix;
1898 prefix.append(depth, ' ');
1899 }
1900
1901 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
1902 const unsigned int labelCount = qname.countLabels();
1903 bool isCNAMEAnswer = false;
1904 for(const auto& rec : lwr.d_records) {
1905 if(!isCNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
1906 isCNAMEAnswer = true;
1907 }
1908
1909 /* if we have a positive answer synthetized from a wildcard,
1910 we need to store the corresponding NSEC/NSEC3 records proving
1911 that the exact name did not exist in the negative cache */
1912 if(needWildcardProof) {
1913 if (nsecTypes.count(rec.d_type)) {
1914 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1915 }
1916 else if (rec.d_type == QType::RRSIG) {
1917 auto rrsig = getRR<RRSIGRecordContent>(rec);
1918 if (rrsig && nsecTypes.count(rrsig->d_type)) {
1919 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1920 }
1921 }
1922 }
1923 if(rec.d_type == QType::RRSIG) {
1924 auto rrsig = getRR<RRSIGRecordContent>(rec);
1925 if (rrsig) {
1926 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
1927 count can be lower than the name's label count if it was
1928 synthetized from the wildcard. Note that the difference might
1929 be > 1. */
1930 if (rec.d_name == qname && rrsig->d_labels < labelCount) {
1931 LOG(prefix<<qname<<": RRSIG indicates the name was synthetized from a wildcard, we need a wildcard proof"<<endl);
1932 needWildcardProof = true;
1933 wildcardLabelsCount = rrsig->d_labels;
1934 }
1935
1936 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
1937 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
1938 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);
1939 }
1940 }
1941 }
1942
1943 // reap all answers from this packet that are acceptable
1944 for(auto& rec : lwr.d_records) {
1945 if(rec.d_type == QType::OPT) {
1946 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
1947 continue;
1948 }
1949 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<<" ");
1950 if(rec.d_type == QType::ANY) {
1951 LOG("NO! - we don't accept 'ANY' data"<<endl);
1952 continue;
1953 }
1954
1955 if(rec.d_name.isPartOf(auth)) {
1956 if(rec.d_type == QType::RRSIG) {
1957 LOG("RRSIG - separate"<<endl);
1958 }
1959 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)) {
1960 LOG("NO! Is from delegation-only zone"<<endl);
1961 s_nodelegated++;
1962 return RCode::NXDomain;
1963 }
1964 else {
1965 bool haveLogged = false;
1966 if (!t_sstorage.domainmap->empty()) {
1967 // Check if we are authoritative for a zone in this answer
1968 DNSName tmp_qname(rec.d_name);
1969 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
1970 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
1971 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
1972 if (auth_domain_iter->first != auth) {
1973 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
1974 continue;
1975 } else {
1976 LOG("YES! - This answer was ");
1977 if (!wasForwarded) {
1978 LOG("retrieved from the local auth store.");
1979 } else {
1980 LOG("received from a server we forward to.");
1981 }
1982 haveLogged = true;
1983 LOG(endl);
1984 }
1985 }
1986 }
1987 if (!haveLogged) {
1988 LOG("YES!"<<endl);
1989 }
1990
1991 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
1992
1993 DNSRecord dr(rec);
1994 dr.d_ttl += d_now.tv_sec;
1995 dr.d_place=DNSResourceRecord::ANSWER;
1996 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
1997 }
1998 }
1999 else
2000 LOG("NO!"<<endl);
2001 }
2002
2003 // supplant
2004 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2005 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)
2006 uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
2007
2008 for(auto& record : i->second.records)
2009 record.d_ttl = lowestTTD; // boom
2010 }
2011
2012 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
2013 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
2014 }
2015
2016 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2017
2018 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
2019 continue;
2020
2021 /* Even if the AA bit is set, additional data cannot be considered
2022 as authoritative. This is especially important during validation
2023 because keeping records in the additional section is allowed even
2024 if the corresponding RRSIGs are not included, without setting the TC
2025 bit, as stated in rfc4035's section 3.1.1. Including RRSIG RRs in a Response:
2026 "When placing a signed RRset in the Additional section, the name
2027 server MUST also place its RRSIG RRs in the Additional section.
2028 If space does not permit inclusion of both the RRset and its
2029 associated RRSIG RRs, the name server MAY retain the RRset while
2030 dropping the RRSIG RRs. If this happens, the name server MUST NOT
2031 set the TC bit solely because these RRSIG RRs didn't fit."
2032 */
2033 bool isAA = lwr.d_aabit && i->first.place != DNSResourceRecord::ADDITIONAL;
2034 if (isAA && isCNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER || i->first.type != QType::CNAME)) {
2035 /*
2036 rfc2181 states:
2037 Note that the answer section of an authoritative answer normally
2038 contains only authoritative data. However when the name sought is an
2039 alias (see section 10.1.1) only the record describing that alias is
2040 necessarily authoritative. Clients should assume that other records
2041 may have come from the server's cache. Where authoritative answers
2042 are required, the client should query again, using the canonical name
2043 associated with the alias.
2044 */
2045 isAA = false;
2046 }
2047
2048 vState recordState = getValidationStatus(i->first.name, false);
2049 LOG(d_prefix<<": got initial zone status "<<vStates[recordState]<<" for record "<<i->first.name<<endl);
2050
2051 if (shouldValidate() && recordState == Secure) {
2052 vState initialState = recordState;
2053
2054 if (isAA) {
2055 if (i->first.place != DNSResourceRecord::ADDITIONAL) {
2056 /* the additional entries can be insecure,
2057 like glue:
2058 "Glue address RRsets associated with delegations MUST NOT be signed"
2059 */
2060 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) {
2061 LOG(d_prefix<<"Validating DNSKEY for "<<i->first.name<<endl);
2062 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth);
2063 }
2064 else {
2065 LOG(d_prefix<<"Validating non-additional record for "<<i->first.name<<endl);
2066 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2067 /* 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 */
2068 if (qtype == QType::NS && i->second.signatures.empty() && recordState == Bogus && haveExactValidationStatus(i->first.name) && getValidationStatus(i->first.name) == Indeterminate) {
2069 recordState = Indeterminate;
2070 }
2071 }
2072 }
2073 }
2074 else {
2075 /* in a non authoritative answer, we only care about the DS record (or lack of) */
2076 if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
2077 LOG(d_prefix<<"Validating DS record for "<<i->first.name<<endl);
2078 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2079 }
2080 }
2081
2082 if (initialState == Secure && state != recordState) {
2083 updateValidationState(state, recordState);
2084 }
2085 }
2086 else {
2087 if (shouldValidate()) {
2088 LOG(d_prefix<<"Skipping validation because the current state is "<<vStates[recordState]<<endl);
2089 }
2090 }
2091
2092 /* We don't need to store NSEC3 records in the positive cache because:
2093 - we don't allow direct NSEC3 queries
2094 - denial of existence proofs in wildcard expanded positive responses are stored in authorityRecs
2095 - denial of existence proofs for negative responses are stored in the negative cache
2096 */
2097 if (i->first.type != QType::NSEC3) {
2098 t_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);
2099 }
2100
2101 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
2102 d_wasVariable=true;
2103 }
2104
2105 return RCode::NoError;
2106 }
2107
2108 void SyncRes::updateDenialValidationState(NegCache::NegCacheEntry& ne, vState& state, const dState denialState, const dState expectedState, bool allowOptOut)
2109 {
2110 if (denialState == expectedState) {
2111 ne.d_validationState = Secure;
2112 }
2113 else {
2114 if (denialState == OPTOUT && allowOptOut) {
2115 LOG(d_prefix<<"OPT-out denial found for "<<ne.d_name<<endl);
2116 ne.d_validationState = Secure;
2117 return;
2118 }
2119 else if (denialState == INSECURE) {
2120 LOG(d_prefix<<"Insecure denial found for "<<ne.d_name<<", returning Insecure"<<endl);
2121 ne.d_validationState = Insecure;
2122 }
2123 else {
2124 LOG(d_prefix<<"Invalid denial found for "<<ne.d_name<<", returning Bogus, res="<<denialState<<", expectedState="<<expectedState<<endl);
2125 ne.d_validationState = Bogus;
2126 }
2127 updateValidationState(state, ne.d_validationState);
2128 }
2129 }
2130
2131 dState SyncRes::getDenialValidationState(NegCache::NegCacheEntry& ne, const vState state, const dState expectedState, bool referralToUnsigned)
2132 {
2133 cspmap_t csp = harvestCSPFromNE(ne);
2134 return getDenial(csp, ne.d_name, ne.d_qtype.getCode(), referralToUnsigned, expectedState == NXQTYPE);
2135 }
2136
2137 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 unsigned int wildcardLabelsCount)
2138 {
2139 bool done = false;
2140
2141 for(auto& rec : lwr.d_records) {
2142 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
2143 continue;
2144
2145 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2146 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
2147 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
2148
2149 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
2150 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
2151 ret.push_back(rec);
2152
2153 NegCache::NegCacheEntry ne;
2154
2155 uint32_t lowestTTL = rec.d_ttl;
2156 /* if we get an NXDomain answer with a CNAME, the name
2157 does exist but the target does not */
2158 ne.d_name = newtarget.empty() ? qname : newtarget;
2159 ne.d_qtype = QType(0); // this encodes 'whole record'
2160 ne.d_auth = rec.d_name;
2161 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2162 ne.d_ttd = d_now.tv_sec + lowestTTL;
2163
2164 if (state == Secure) {
2165 dState denialState = getDenialValidationState(ne, state, NXDOMAIN, false);
2166 updateDenialValidationState(ne, state, denialState, NXDOMAIN, false);
2167 }
2168 else {
2169 ne.d_validationState = state;
2170 }
2171
2172 /* if we get an NXDomain answer with a CNAME, let's not cache the
2173 target, even the server was authoritative for it,
2174 and do an additional query for the CNAME target.
2175 We have a regression test making sure we do exactly that.
2176 */
2177 if(!wasVariable() && newtarget.empty()) {
2178 t_sstorage.negcache.add(ne);
2179 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
2180 ne.d_name = ne.d_name.getLastLabel();
2181 t_sstorage.negcache.add(ne);
2182 }
2183 }
2184
2185 negindic=true;
2186 }
2187 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
2188 ret.push_back(rec);
2189 if (auto content = getRR<CNAMERecordContent>(rec)) {
2190 newtarget=content->getTarget();
2191 }
2192 }
2193 /* if we have a positive answer synthetized from a wildcard, we need to
2194 return the corresponding NSEC/NSEC3 records from the AUTHORITY section
2195 proving that the exact name did not exist */
2196 else if(needWildcardProof && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::AUTHORITY) {
2197 ret.push_back(rec); // enjoy your DNSSEC
2198 }
2199 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
2200 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
2201 (
2202 rec.d_type==qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType(QType::ANY))
2203 )
2204 )
2205 {
2206 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
2207
2208 done=true;
2209 ret.push_back(rec);
2210
2211 if (state == Secure && needWildcardProof) {
2212 /* We have a positive answer synthetized from a wildcard, we need to check that we have
2213 proof that the exact name doesn't exist so the wildcard can be used,
2214 as described in section 5.3.4 of RFC 4035 and 5.3 of FRC 7129.
2215 */
2216 NegCache::NegCacheEntry ne;
2217
2218 uint32_t lowestTTL = rec.d_ttl;
2219 ne.d_name = qname;
2220 ne.d_qtype = QType(0); // this encodes 'whole record'
2221 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2222
2223 cspmap_t csp = harvestCSPFromNE(ne);
2224 dState res = getDenial(csp, qname, ne.d_qtype.getCode(), false, false, false, wildcardLabelsCount);
2225 if (res != NXDOMAIN) {
2226 vState st = Bogus;
2227 if (res == INSECURE) {
2228 /* Some part could not be validated, for example a NSEC3 record with a too large number of iterations,
2229 this is not enough to warrant a Bogus, but go Insecure. */
2230 st = Insecure;
2231 LOG(d_prefix<<"Unable to validate denial in wildcard expanded positive response found for "<<qname<<", returning Insecure, res="<<res<<endl);
2232 }
2233 else {
2234 LOG(d_prefix<<"Invalid denial in wildcard expanded positive response found for "<<qname<<", returning Bogus, res="<<res<<endl);
2235 }
2236
2237 updateValidationState(state, st);
2238 /* we already stored the record with a different validation status, let's fix it */
2239 t_RC->updateValidationStatus(d_now.tv_sec, qname, qtype, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, lwr.d_aabit, st);
2240 }
2241 }
2242 }
2243 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER) {
2244 if(rec.d_type != QType::RRSIG || rec.d_name == qname)
2245 ret.push_back(rec); // enjoy your DNSSEC
2246 }
2247 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::NS && qname.isPartOf(rec.d_name)) {
2248 if(moreSpecificThan(rec.d_name,auth)) {
2249 newauth=rec.d_name;
2250 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2251 realreferral=true;
2252 }
2253 else {
2254 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
2255 }
2256 if (auto content = getRR<NSRecordContent>(rec)) {
2257 nsset.insert(content->getNS());
2258 }
2259 }
2260 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
2261 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2262 }
2263 else if(realreferral && rec.d_place==DNSResourceRecord::AUTHORITY && (rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && newauth.isPartOf(auth)) {
2264 /* we might have received a denial of the DS, let's check */
2265 if (state == Secure) {
2266 NegCache::NegCacheEntry ne;
2267 ne.d_auth = auth;
2268 ne.d_name = newauth;
2269 ne.d_qtype = QType::DS;
2270 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2271 uint32_t lowestTTL = rec.d_ttl;
2272 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2273
2274 dState denialState = getDenialValidationState(ne, state, NXQTYPE, true);
2275
2276 if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
2277 ne.d_ttd = lowestTTL + d_now.tv_sec;
2278 ne.d_validationState = Secure;
2279 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
2280
2281 if(!wasVariable()) {
2282 t_sstorage.negcache.add(ne);
2283 }
2284
2285 if (qname == newauth && qtype == QType::DS) {
2286 /* we are actually done! */
2287 negindic=true;
2288 nsset.clear();
2289 }
2290 }
2291 }
2292 }
2293 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2294 lwr.d_rcode==RCode::NoError && qname.isPartOf(rec.d_name)) {
2295 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
2296
2297 if(!newtarget.empty()) {
2298 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
2299 }
2300 else {
2301 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2302 ret.push_back(rec);
2303
2304 NegCache::NegCacheEntry ne;
2305 ne.d_auth = rec.d_name;
2306 uint32_t lowestTTL = rec.d_ttl;
2307 ne.d_name = qname;
2308 ne.d_qtype = qtype;
2309 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2310 ne.d_ttd = d_now.tv_sec + lowestTTL;
2311
2312 if (state == Secure) {
2313 dState denialState = getDenialValidationState(ne, state, NXQTYPE, false);
2314 updateDenialValidationState(ne, state, denialState, NXQTYPE, qtype == QType::DS);
2315 } else {
2316 ne.d_validationState = state;
2317 }
2318
2319 if(!wasVariable()) {
2320 if(qtype.getCode()) { // prevents us from blacking out a whole domain
2321 t_sstorage.negcache.add(ne);
2322 }
2323 }
2324 negindic=true;
2325 }
2326 }
2327 }
2328
2329 return done;
2330 }
2331
2332 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)
2333 {
2334 int resolveret;
2335 s_outqueries++;
2336 d_outqueries++;
2337
2338 if(d_outqueries + d_throttledqueries > s_maxqperq) {
2339 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
2340 }
2341
2342 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
2343 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");
2344 }
2345
2346 if(doTCP) {
2347 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
2348 s_tcpoutqueries++;
2349 d_tcpoutqueries++;
2350 }
2351
2352 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
2353 LOG(prefix<<qname<<": query handled by Lua"<<endl);
2354 }
2355 else {
2356 ednsmask=getEDNSSubnetMask(d_requestor, qname, remoteIP);
2357 if(ednsmask) {
2358 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
2359 s_ecsqueries++;
2360 }
2361 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(),
2362 doTCP, sendRDQuery, &d_now, ednsmask, &lwr); // <- we go out on the wire!
2363 if(ednsmask) {
2364 s_ecsresponses++;
2365 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
2366 }
2367 }
2368
2369 /* preoutquery killed the query by setting dq.rcode to -3 */
2370 if(resolveret==-3) {
2371 throw ImmediateServFailException("Query killed by policy");
2372 }
2373
2374 d_totUsec += lwr.d_usec;
2375 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
2376
2377 if(resolveret != 1) {
2378 /* Error while resolving */
2379 if(resolveret == 0) {
2380 /* Time out */
2381
2382 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
2383 d_timeouts++;
2384 s_outgoingtimeouts++;
2385
2386 if(remoteIP.sin4.sin_family == AF_INET)
2387 s_outgoing4timeouts++;
2388 else
2389 s_outgoing6timeouts++;
2390 }
2391 else if(resolveret == -2) {
2392 /* OS resource limit reached */
2393 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
2394 g_stats.resourceLimits++;
2395 }
2396 else {
2397 /* -1 means server unreachable */
2398 s_unreachables++;
2399 d_unreachables++;
2400 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
2401 }
2402
2403 if(resolveret != -2) { // don't account for resource limits, they are our own fault
2404 t_sstorage.nsSpeeds[nsName].submit(remoteIP, 1000000, &d_now); // 1 sec
2405
2406 // code below makes sure we don't filter COM or the root
2407 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) {
2408 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
2409 // mark server as down
2410 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
2411 }
2412 else if (resolveret == -1) {
2413 // unreachable, 1 minute or 100 queries
2414 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
2415 }
2416 else {
2417 // timeout
2418 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
2419 }
2420 }
2421
2422 return false;
2423 }
2424
2425 /* we got an answer */
2426 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
2427 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
2428 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2429 return false;
2430 }
2431
2432 /* this server sent a valid answer, mark it backup up if it was down */
2433 if(s_serverdownmaxfails > 0) {
2434 t_sstorage.fails.clear(remoteIP);
2435 }
2436
2437 if(lwr.d_tcbit) {
2438 *truncated = true;
2439
2440 if (doTCP) {
2441 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
2442 /* let's treat that as a ServFail answer from this server */
2443 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2444 return false;
2445 }
2446
2447 return true;
2448 }
2449
2450 return true;
2451 }
2452
2453 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)
2454 {
2455 string prefix;
2456 if(doLog()) {
2457 prefix=d_prefix;
2458 prefix.append(depth, ' ');
2459 }
2460
2461 if(s_minimumTTL) {
2462 for(auto& rec : lwr.d_records) {
2463 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
2464 }
2465 }
2466
2467 bool needWildcardProof = false;
2468 unsigned int wildcardLabelsCount;
2469 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, needWildcardProof, wildcardLabelsCount);
2470 if (*rcode != RCode::NoError) {
2471 return true;
2472 }
2473
2474 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
2475
2476 set<DNSName> nsset;
2477 bool realreferral=false, negindic=false;
2478 DNSName newauth;
2479 DNSName newtarget;
2480
2481 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof, wildcardLabelsCount);
2482
2483 if(done){
2484 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
2485 LOG(prefix<<qname<<": validation status is "<<vStates[state]<<endl);
2486 *rcode = RCode::NoError;
2487 return true;
2488 }
2489
2490 if(!newtarget.empty()) {
2491 if(newtarget == qname) {
2492 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
2493 *rcode = RCode::ServFail;
2494 return true;
2495 }
2496
2497 if(depth > 10) {
2498 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
2499 *rcode = RCode::ServFail;
2500 return true;
2501 }
2502
2503 if (qtype == QType::DS) {
2504 LOG(prefix<<qname<<": status=got a CNAME referral, but we are looking for a DS"<<endl);
2505
2506 if(d_doDNSSEC)
2507 addNXNSECS(ret, lwr.d_records);
2508
2509 *rcode = RCode::NoError;
2510 return true;
2511 }
2512 else {
2513 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
2514
2515 set<GetBestNSAnswer> beenthere2;
2516 vState cnameState = Indeterminate;
2517 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState);
2518 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
2519 updateValidationState(state, cnameState);
2520 return true;
2521 }
2522 }
2523
2524 if(lwr.d_rcode == RCode::NXDomain) {
2525 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
2526
2527 if(d_doDNSSEC)
2528 addNXNSECS(ret, lwr.d_records);
2529
2530 *rcode = RCode::NXDomain;
2531 return true;
2532 }
2533
2534 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
2535 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
2536
2537 if(state == Secure && lwr.d_aabit && !negindic) {
2538 updateValidationState(state, Bogus);
2539 }
2540
2541 if(d_doDNSSEC)
2542 addNXNSECS(ret, lwr.d_records);
2543
2544 *rcode = RCode::NoError;
2545 return true;
2546 }
2547
2548 if(realreferral) {
2549 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
2550
2551 nameservers.clear();
2552 for (auto const &nameserver : nsset) {
2553 if (d_wantsRPZ) {
2554 d_appliedPolicy = dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
2555 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2556 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
2557 *rcode = -2;
2558 return true;
2559 }
2560 }
2561 nameservers.insert({nameserver, {{}, false}});
2562 }
2563 LOG("looping to them"<<endl);
2564 *gotNewServers = true;
2565 auth=newauth;
2566
2567 return false;
2568 }
2569
2570 return false;
2571 }
2572
2573 /** returns:
2574 * -1 in case of no results
2575 * -2 when a FilterEngine Policy was hit
2576 * rcode otherwise
2577 */
2578 int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
2579 vector<DNSRecord>&ret,
2580 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state)
2581 {
2582 auto luaconfsLocal = g_luaconfs.getLocal();
2583 string prefix;
2584 if(doLog()) {
2585 prefix=d_prefix;
2586 prefix.append(depth, ' ');
2587 }
2588
2589 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
2590
2591 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
2592 return -2;
2593 }
2594
2595 LOG(endl);
2596
2597 for(;;) { // we may get more specific nameservers
2598 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
2599
2600 for(auto tns=rnameservers.cbegin();;++tns) {
2601 if(tns==rnameservers.cend()) {
2602 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
2603 if(!auth.isRoot() && flawedNSSet) {
2604 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
2605
2606 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
2607 g_stats.nsSetInvalidations++;
2608 }
2609 return -1;
2610 }
2611
2612 bool cacheOnly = false;
2613 // this line needs to identify the 'self-resolving' behaviour
2614 if(qname == *tns && (qtype.getCode() == QType::A || qtype.getCode() == QType::AAAA)) {
2615 /* we might have a glue entry in cache so let's try this NS
2616 but only if we have enough in the cache to know how to reach it */
2617 LOG(prefix<<qname<<": Using NS to resolve itself, but only using what we have in cache ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
2618 cacheOnly = true;
2619 }
2620
2621 typedef vector<ComboAddress> remoteIPs_t;
2622 remoteIPs_t remoteIPs;
2623 remoteIPs_t::const_iterator remoteIP;
2624 bool pierceDontQuery=false;
2625 bool sendRDQuery=false;
2626 boost::optional<Netmask> ednsmask;
2627 LWResult lwr;
2628 const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty());
2629 int rcode = RCode::NoError;
2630 bool gotNewServers = false;
2631
2632 if(tns->empty() && !wasForwarded) {
2633 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
2634 /* setting state to indeterminate since validation is disabled for local auth zone,
2635 and Insecure would be misleading. */
2636 state = Indeterminate;
2637 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
2638 lwr.d_tcbit=false;
2639 lwr.d_aabit=true;
2640
2641 /* we have received an answer, are we done ? */
2642 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
2643 if (done) {
2644 return rcode;
2645 }
2646 if (gotNewServers) {
2647 break;
2648 }
2649 }
2650 else {
2651 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
2652 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly);
2653
2654 if(remoteIPs.empty()) {
2655 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
2656 flawedNSSet=true;
2657 continue;
2658 }
2659 else {
2660 bool hitPolicy{false};
2661 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
2662 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2663 if(remoteIP != remoteIPs.cbegin()) {
2664 LOG(", ");
2665 }
2666 LOG(remoteIP->toString());
2667 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
2668 hitPolicy = true;
2669 }
2670 }
2671 LOG(endl);
2672 if (hitPolicy) //implies d_wantsRPZ
2673 return -2;
2674 }
2675
2676 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2677 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
2678
2679 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
2680 continue;
2681 }
2682
2683 bool truncated = false;
2684 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2685 *tns, *remoteIP, false, &truncated);
2686 if (gotAnswer && truncated ) {
2687 /* retry, over TCP this time */
2688 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2689 *tns, *remoteIP, true, &truncated);
2690 }
2691
2692 if (!gotAnswer) {
2693 continue;
2694 }
2695
2696 LOG(prefix<<qname<<": Got "<<(unsigned int)lwr.d_records.size()<<" answers from "<<*tns<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
2697
2698 /* // for you IPv6 fanatics :-)
2699 if(remoteIP->sin4.sin_family==AF_INET6)
2700 lwr.d_usec/=3;
2701 */
2702 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
2703
2704 t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
2705
2706 /* we have received an answer, are we done ? */
2707 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
2708 if (done) {
2709 return rcode;
2710 }
2711 if (gotNewServers) {
2712 break;
2713 }
2714 /* was lame */
2715 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
2716 }
2717
2718 if (gotNewServers) {
2719 break;
2720 }
2721
2722 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
2723 continue;
2724
2725 }
2726 }
2727 }
2728 return -1;
2729 }
2730
2731 void SyncRes::setIncomingECS(boost::optional<const EDNSSubnetOpts&> incomingECS)
2732 {
2733 d_incomingECS = incomingECS;
2734 if (incomingECS) {
2735 if (d_incomingECS->source.getBits() == 0) {
2736 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0.
2737 But using an empty ECS in that case would mean inserting
2738 a non ECS-specific entry into the cache, preventing any further
2739 ECS-specific query to be sent.
2740 So instead we use the trick described in section 7.1.2:
2741 "The subsequent Recursive Resolver query to the Authoritative Nameserver
2742 will then either not include an ECS option or MAY optionally include
2743 its own address information, which is what the Authoritative
2744 Nameserver will almost certainly use to generate any Tailored
2745 Response in lieu of an option. This allows the answer to be handled
2746 by the same caching mechanism as other queries, with an explicit
2747 indicator of the applicable scope. Subsequent Stub Resolver queries
2748 for /0 can then be answered from this cached response.
2749 */
2750 d_incomingECS = s_ecsScopeZero;
2751 d_incomingECSNetwork = s_ecsScopeZero.source.getMaskedNetwork();
2752 }
2753 else {
2754 uint8_t bits = std::min(incomingECS->source.getBits(), (incomingECS->source.isIpv4() ? s_ecsipv4limit : s_ecsipv6limit));
2755 d_incomingECS->source = Netmask(incomingECS->source.getNetwork(), bits);
2756 d_incomingECSNetwork = d_incomingECS->source.getMaskedNetwork();
2757 }
2758 }
2759 else {
2760 d_incomingECSNetwork = ComboAddress();
2761 }
2762 }
2763
2764 boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem)
2765 {
2766 boost::optional<Netmask> result;
2767 ComboAddress trunc;
2768 uint8_t bits;
2769 if(d_incomingECSFound) {
2770 trunc = d_incomingECSNetwork;
2771 bits = d_incomingECS->source.getBits();
2772 }
2773 else if(!local.isIPv4() || local.sin4.sin_addr.s_addr) { // detect unset 'requestor'
2774 trunc = local;
2775 bits = local.isIPv4() ? 32 : 128;
2776 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
2777 }
2778 else {
2779 /* nothing usable */
2780 return result;
2781 }
2782
2783 if(s_ednsdomains.check(dn) || s_ednssubnets.match(rem)) {
2784 trunc.truncate(bits);
2785 return boost::optional<Netmask>(Netmask(trunc, bits));
2786 }
2787
2788 return result;
2789 }
2790
2791 void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
2792 {
2793 vector<string> parts;
2794 stringtok(parts, wlist, ",; ");
2795 for(const auto& a : parts) {
2796 try {
2797 s_ednssubnets.addMask(Netmask(a));
2798 }
2799 catch(...) {
2800 s_ednsdomains.add(DNSName(a));
2801 }
2802 }
2803 }
2804
2805 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
2806 int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
2807 {
2808 struct timeval now;
2809 gettimeofday(&now, 0);
2810
2811 SyncRes sr(now);
2812 int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
2813
2814 return res;
2815 }
2816
2817 int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
2818 SyncRes sr(now);
2819 sr.setDoEDNS0(true);
2820 sr.setUpdatingRootNS();
2821 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
2822 sr.setDNSSECValidationRequested(g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate);
2823 sr.setAsyncCallback(asyncCallback);
2824
2825 vector<DNSRecord> ret;
2826 int res=-1;
2827 try {
2828 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
2829 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
2830 auto state = sr.getValidationState();
2831 if (state == Bogus)
2832 throw PDNSException("Got Bogus validation result for .|NS");
2833 }
2834 return res;
2835 }
2836 catch(const PDNSException& e) {
2837 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2838 }
2839 catch(const ImmediateServFailException& e) {
2840 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2841 }
2842 catch(const std::exception& e) {
2843 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
2844 }
2845 catch(...) {
2846 L<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
2847 }
2848
2849 if(!res) {
2850 L<<Logger::Notice<<"Refreshed . records"<<endl;
2851 }
2852 else
2853 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
2854
2855 return res;
2856 }