]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/syncres.cc
Merge pull request #6200 from aerique/bugfix/backport-6095
[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_class != QClass::IN) {
901 continue;
902 }
903
904 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
905
906 if (!wasAuthZone && shouldValidate() && wasAuth && state == Indeterminate && d_requireAuthData) {
907 /* This means we couldn't figure out the state when this entry was cached,
908 most likely because we hadn't computed the zone cuts yet. */
909 /* make sure they are computed before validating */
910 DNSName subdomain(qname);
911 /* if we are retrieving a DS, we only care about the state of the parent zone */
912 if(qtype == QType::DS)
913 subdomain.chopOff();
914
915 computeZoneCuts(subdomain, g_rootdnsname, depth);
916
917 vState recordState = getValidationStatus(qname, false);
918 if (recordState == Secure) {
919 LOG(prefix<<qname<<": got Indeterminate state from the CNAME cache, validating.."<<endl);
920 state = SyncRes::validateRecordsWithSigs(depth, qname, QType(QType::CNAME), qname, cset, signatures);
921 if (state != Indeterminate) {
922 LOG(prefix<<qname<<": got Indeterminate state from the CNAME cache, new validation result is "<<vStates[state]<<endl);
923 t_RC->updateValidationStatus(d_now.tv_sec, qname, QType(QType::CNAME), d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_requireAuthData, state);
924 }
925 }
926 }
927
928 LOG(prefix<<qname<<": Found cache CNAME hit for '"<< qname << "|CNAME" <<"' to '"<<j->d_content->getZoneRepresentation()<<"', validation state is "<<vStates[state]<<endl);
929
930 DNSRecord dr=*j;
931 dr.d_ttl-=d_now.tv_sec;
932 ret.push_back(dr);
933
934 for(const auto& signature : signatures) {
935 DNSRecord sigdr;
936 sigdr.d_type=QType::RRSIG;
937 sigdr.d_name=qname;
938 sigdr.d_ttl=j->d_ttl - d_now.tv_sec;
939 sigdr.d_content=signature;
940 sigdr.d_place=DNSResourceRecord::ANSWER;
941 sigdr.d_class=QClass::IN;
942 ret.push_back(sigdr);
943 }
944
945 for(const auto& rec : authorityRecs) {
946 DNSRecord authDR(*rec);
947 authDR.d_ttl=j->d_ttl - d_now.tv_sec;
948 ret.push_back(authDR);
949 }
950
951 if(qtype != QType::CNAME) { // perhaps they really wanted a CNAME!
952 set<GetBestNSAnswer>beenthere;
953
954 vState cnameState = Indeterminate;
955 const auto cnameContent = getRR<CNAMERecordContent>(*j);
956 if (cnameContent) {
957 res=doResolve(cnameContent->getTarget(), qtype, ret, depth+1, beenthere, cnameState);
958 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
959 updateValidationState(state, cnameState);
960 }
961 }
962 else
963 res=0;
964
965 return true;
966 }
967 }
968 }
969 LOG(prefix<<qname<<": No CNAME cache hit of '"<< qname << "|CNAME" <<"' found"<<endl);
970 return false;
971 }
972
973 namespace {
974 struct CacheEntry
975 {
976 vector<DNSRecord> records;
977 vector<shared_ptr<RRSIGRecordContent>> signatures;
978 uint32_t signaturesTTL{std::numeric_limits<uint32_t>::max()};
979 };
980 struct CacheKey
981 {
982 DNSName name;
983 uint16_t type;
984 DNSResourceRecord::Place place;
985 bool operator<(const CacheKey& rhs) const {
986 return tie(name, type) < tie(rhs.name, rhs.type);
987 }
988 };
989 typedef map<CacheKey, CacheEntry> tcache_t;
990 }
991
992 static void reapRecordsFromNegCacheEntryForValidation(tcache_t& tcache, const vector<DNSRecord>& records)
993 {
994 for (const auto& rec : records) {
995 if (rec.d_type == QType::RRSIG) {
996 auto rrsig = getRR<RRSIGRecordContent>(rec);
997 if (rrsig) {
998 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
999 }
1000 } else {
1001 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(rec);
1002 }
1003 }
1004 }
1005
1006 /*!
1007 * Convience function to push the records from records into ret with a new TTL
1008 *
1009 * \param records DNSRecords that need to go into ret
1010 * \param ttl The new TTL for these records
1011 * \param ret The vector of DNSRecords that should contian the records with the modified TTL
1012 */
1013 static void addTTLModifiedRecords(const vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
1014 for (const auto& rec : records) {
1015 DNSRecord r(rec);
1016 r.d_ttl = ttl;
1017 ret.push_back(r);
1018 }
1019 }
1020
1021 void SyncRes::computeNegCacheValidationStatus(NegCache::NegCacheEntry& ne, const DNSName& qname, const QType& qtype, const int res, vState& state, unsigned int depth)
1022 {
1023 DNSName subdomain(qname);
1024 /* if we are retrieving a DS, we only care about the state of the parent zone */
1025 if(qtype == QType::DS)
1026 subdomain.chopOff();
1027
1028 computeZoneCuts(subdomain, g_rootdnsname, depth);
1029
1030 tcache_t tcache;
1031 reapRecordsFromNegCacheEntryForValidation(tcache, ne.authoritySOA.records);
1032 reapRecordsFromNegCacheEntryForValidation(tcache, ne.authoritySOA.signatures);
1033 reapRecordsFromNegCacheEntryForValidation(tcache, ne.DNSSECRecords.records);
1034 reapRecordsFromNegCacheEntryForValidation(tcache, ne.DNSSECRecords.signatures);
1035
1036 for (const auto& entry : tcache) {
1037 // this happens when we did store signatures, but passed on the records themselves
1038 if (entry.second.records.empty()) {
1039 continue;
1040 }
1041
1042 const DNSName& owner = entry.first.name;
1043
1044 vState recordState = getValidationStatus(owner, false);
1045 if (state == Indeterminate) {
1046 state = recordState;
1047 }
1048
1049 if (recordState == Secure) {
1050 recordState = SyncRes::validateRecordsWithSigs(depth, qname, qtype, owner, entry.second.records, entry.second.signatures);
1051 }
1052
1053 if (recordState != Indeterminate && recordState != state) {
1054 updateValidationState(state, recordState);
1055 if (state != Secure) {
1056 break;
1057 }
1058 }
1059 }
1060
1061 if (state == Secure) {
1062 dState expectedState = res == RCode::NXDomain ? NXDOMAIN : NXQTYPE;
1063 dState denialState = getDenialValidationState(ne, state, expectedState, false);
1064 updateDenialValidationState(ne, state, denialState, expectedState, qtype == QType::DS);
1065 }
1066 if (state != Indeterminate) {
1067 /* validation succeeded, let's update the cache entry so we don't have to validate again */
1068 t_sstorage.negcache.updateValidationStatus(ne.d_name, ne.d_qtype, state);
1069 }
1070 }
1071
1072 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)
1073 {
1074 bool giveNegative=false;
1075
1076 string prefix;
1077 if(doLog()) {
1078 prefix=d_prefix;
1079 prefix.append(depth, ' ');
1080 }
1081
1082 // 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)
1083 DNSName sqname(qname);
1084 QType sqt(qtype);
1085 uint32_t sttl=0;
1086 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
1087 vState cachedState;
1088 NegCache::NegCacheEntry ne;
1089
1090 if(s_rootNXTrust &&
1091 t_sstorage.negcache.getRootNXTrust(qname, d_now, ne) &&
1092 ne.d_auth.isRoot() &&
1093 !(wasForwardedOrAuthZone && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
1094 sttl = ne.d_ttd - d_now.tv_sec;
1095 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' & '"<<ne.d_name<<"' for another "<<sttl<<" seconds"<<endl);
1096 res = RCode::NXDomain;
1097 giveNegative = true;
1098 cachedState = ne.d_validationState;
1099 }
1100 else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) &&
1101 !(wasForwardedOrAuthZone && ne.d_auth != authname)) { // Only the authname nameserver can neg cache entries
1102
1103 /* If we are looking for a DS, discard NXD if auth == qname
1104 and ask for a specific denial instead */
1105 if (qtype != QType::DS || ne.d_qtype.getCode() || ne.d_auth != qname ||
1106 t_sstorage.negcache.get(qname, qtype, d_now, ne, true))
1107 {
1108 res = 0;
1109 sttl = ne.d_ttd - d_now.tv_sec;
1110 giveNegative = true;
1111 cachedState = ne.d_validationState;
1112 if(ne.d_qtype.getCode()) {
1113 LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
1114 res = RCode::NoError;
1115 }
1116 else {
1117 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
1118 res = RCode::NXDomain;
1119 }
1120 }
1121 }
1122
1123 if (giveNegative) {
1124
1125 state = cachedState;
1126
1127 if (!wasAuthZone && shouldValidate() && state == Indeterminate) {
1128 LOG(prefix<<qname<<": got Indeterminate state for records retrieved from the negative cache, validating.."<<endl);
1129 computeNegCacheValidationStatus(ne, qname, qtype, res, state, depth);
1130 }
1131
1132 // Transplant SOA to the returned packet
1133 addTTLModifiedRecords(ne.authoritySOA.records, sttl, ret);
1134 if(d_doDNSSEC) {
1135 addTTLModifiedRecords(ne.authoritySOA.signatures, sttl, ret);
1136 addTTLModifiedRecords(ne.DNSSECRecords.records, sttl, ret);
1137 addTTLModifiedRecords(ne.DNSSECRecords.signatures, sttl, ret);
1138 }
1139
1140 LOG(prefix<<qname<<": updating validation state with negative cache content for "<<qname<<" to "<<vStates[state]<<endl);
1141 return true;
1142 }
1143
1144 vector<DNSRecord> cset;
1145 bool found=false, expired=false;
1146 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
1147 vector<std::shared_ptr<DNSRecord>> authorityRecs;
1148 uint32_t ttl=0;
1149 bool wasCachedAuth;
1150 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) {
1151
1152 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
1153
1154 if (!wasAuthZone && shouldValidate() && wasCachedAuth && cachedState == Indeterminate && d_requireAuthData) {
1155
1156 /* This means we couldn't figure out the state when this entry was cached,
1157 most likely because we hadn't computed the zone cuts yet. */
1158 /* make sure they are computed before validating */
1159 DNSName subdomain(sqname);
1160 /* if we are retrieving a DS, we only care about the state of the parent zone */
1161 if(qtype == QType::DS)
1162 subdomain.chopOff();
1163
1164 computeZoneCuts(subdomain, g_rootdnsname, depth);
1165
1166 vState recordState = getValidationStatus(qname, false);
1167 if (recordState == Secure) {
1168 LOG(prefix<<sqname<<": got Indeterminate state from the cache, validating.."<<endl);
1169 cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures);
1170 }
1171 else {
1172 cachedState = recordState;
1173 }
1174
1175 if (cachedState != Indeterminate) {
1176 LOG(prefix<<qname<<": got Indeterminate state from the cache, validation result is "<<vStates[cachedState]<<endl);
1177 t_RC->updateValidationStatus(d_now.tv_sec, sqname, sqt, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_requireAuthData, cachedState);
1178 }
1179 }
1180
1181 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
1182
1183 LOG(j->d_content->getZoneRepresentation());
1184
1185 if (j->d_class != QClass::IN) {
1186 continue;
1187 }
1188
1189 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
1190 DNSRecord dr=*j;
1191 ttl = (dr.d_ttl-=d_now.tv_sec);
1192 ret.push_back(dr);
1193 LOG("[ttl="<<dr.d_ttl<<"] ");
1194 found=true;
1195 }
1196 else {
1197 LOG("[expired] ");
1198 expired=true;
1199 }
1200 }
1201
1202 for(const auto& signature : signatures) {
1203 DNSRecord dr;
1204 dr.d_type=QType::RRSIG;
1205 dr.d_name=sqname;
1206 dr.d_ttl=ttl;
1207 dr.d_content=signature;
1208 dr.d_place = DNSResourceRecord::ANSWER;
1209 dr.d_class=QClass::IN;
1210 ret.push_back(dr);
1211 }
1212
1213 for(const auto& rec : authorityRecs) {
1214 DNSRecord dr(*rec);
1215 dr.d_ttl=ttl;
1216 ret.push_back(dr);
1217 }
1218
1219 LOG(endl);
1220 if(found && !expired) {
1221 if (!giveNegative)
1222 res=0;
1223 LOG(prefix<<qname<<": updating validation state with cache content for "<<qname<<" to "<<vStates[cachedState]<<endl);
1224 state = cachedState;
1225 return true;
1226 }
1227 else
1228 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
1229 }
1230
1231 return false;
1232 }
1233
1234 bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
1235 {
1236 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
1237 }
1238
1239 struct speedOrder
1240 {
1241 speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
1242 bool operator()(const DNSName &a, const DNSName &b) const
1243 {
1244 return d_speeds[a] < d_speeds[b];
1245 }
1246 map<DNSName, double>& d_speeds;
1247 };
1248
1249 inline vector<DNSName> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
1250 {
1251 vector<DNSName> rnameservers;
1252 rnameservers.reserve(tnameservers.size());
1253 for(const auto& tns: tnameservers) {
1254 rnameservers.push_back(tns.first);
1255 if(tns.first.empty()) // this was an authoritative OOB zone, don't pollute the nsSpeeds with that
1256 return rnameservers;
1257 }
1258 map<DNSName, double> speeds;
1259
1260 for(const auto& val: rnameservers) {
1261 double speed;
1262 speed=t_sstorage.nsSpeeds[val].get(&d_now);
1263 speeds[val]=speed;
1264 }
1265 random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
1266 speedOrder so(speeds);
1267 stable_sort(rnameservers.begin(),rnameservers.end(), so);
1268
1269 if(doLog()) {
1270 LOG(prefix<<"Nameservers: ");
1271 for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
1272 if(i!=rnameservers.begin()) {
1273 LOG(", ");
1274 if(!((i-rnameservers.begin())%3)) {
1275 LOG(endl<<prefix<<" ");
1276 }
1277 }
1278 LOG((i->empty() ? string("<empty>") : i->toString())<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
1279 }
1280 LOG(endl);
1281 }
1282 return rnameservers;
1283 }
1284
1285 static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<RRSIGRecordContent>& rrsig)
1286 {
1287 uint32_t res = 0;
1288 if (now < rrsig->d_sigexpire) {
1289 res = static_cast<uint32_t>(rrsig->d_sigexpire) - now;
1290 }
1291 return res;
1292 }
1293
1294 static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
1295
1296 /* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1297 *
1298 * \param records The records to parse for the authority SOA and NSEC(3) records
1299 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1300 */
1301 static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne, const time_t now, uint32_t* lowestTTL) {
1302 for(const auto& rec : records) {
1303 if(rec.d_place != DNSResourceRecord::AUTHORITY)
1304 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1305 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1306 // records MUST be in the same section as the records they cover.
1307 // Hence, we ignore all records outside of the AUTHORITY section.
1308 continue;
1309
1310 if(rec.d_type == QType::RRSIG) {
1311 auto rrsig = getRR<RRSIGRecordContent>(rec);
1312 if(rrsig) {
1313 if(rrsig->d_type == QType::SOA) {
1314 ne.authoritySOA.signatures.push_back(rec);
1315 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1316 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1317 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1318 }
1319 }
1320 if(nsecTypes.count(rrsig->d_type)) {
1321 ne.DNSSECRecords.signatures.push_back(rec);
1322 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1323 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1324 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1325 }
1326 }
1327 }
1328 continue;
1329 }
1330 if(rec.d_type == QType::SOA) {
1331 ne.authoritySOA.records.push_back(rec);
1332 if (lowestTTL) {
1333 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1334 }
1335 continue;
1336 }
1337 if(nsecTypes.count(rec.d_type)) {
1338 ne.DNSSECRecords.records.push_back(rec);
1339 if (lowestTTL) {
1340 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1341 }
1342 continue;
1343 }
1344 }
1345 }
1346
1347 static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
1348 {
1349 cspmap_t cspmap;
1350 for(const auto& rec : ne.DNSSECRecords.signatures) {
1351 if(rec.d_type == QType::RRSIG) {
1352 auto rrc = getRR<RRSIGRecordContent>(rec);
1353 if (rrc) {
1354 cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
1355 }
1356 }
1357 }
1358 for(const auto& rec : ne.DNSSECRecords.records) {
1359 cspmap[{rec.d_name, rec.d_type}].records.push_back(rec.d_content);
1360 }
1361 return cspmap;
1362 }
1363
1364 // TODO remove after processRecords is fixed!
1365 // Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
1366 static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1367 {
1368 NegCache::NegCacheEntry ne;
1369 harvestNXRecords(records, ne, 0, nullptr);
1370 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
1371 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
1372 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
1373 }
1374
1375 bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
1376 {
1377 if(d_wantsRPZ) {
1378 for (auto const &ns : nameservers) {
1379 d_appliedPolicy = dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
1380 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1381 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1382 return true;
1383 }
1384
1385 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1386 for (auto const &address : ns.second.first) {
1387 d_appliedPolicy = dfe.getProcessingPolicy(address, d_discardedPolicies);
1388 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1389 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1390 return true;
1391 }
1392 }
1393 }
1394 }
1395 return false;
1396 }
1397
1398 bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
1399 {
1400 if (d_wantsRPZ) {
1401 d_appliedPolicy = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies);
1402 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
1403 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
1404 return true;
1405 }
1406 }
1407 return false;
1408 }
1409
1410 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)
1411 {
1412 vector<ComboAddress> result;
1413
1414 if(!tns->empty()) {
1415 LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
1416 result = getAddrs(*tns, depth+2, beenthere, cacheOnly);
1417 pierceDontQuery=false;
1418 }
1419 else {
1420 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
1421
1422 result = nameservers[*tns].first;
1423 if(result.size() > 1) {
1424 LOG("s");
1425 }
1426 LOG(endl);
1427
1428 sendRDQuery = nameservers[*tns].second;
1429 pierceDontQuery=true;
1430 }
1431 return result;
1432 }
1433
1434 bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1435 {
1436 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
1437 LOG(prefix<<qname<<": server throttled "<<endl);
1438 s_throttledqueries++; d_throttledqueries++;
1439 return true;
1440 }
1441 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
1442 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
1443 s_throttledqueries++; d_throttledqueries++;
1444 return true;
1445 }
1446 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
1447 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
1448 s_dontqueries++;
1449 return true;
1450 }
1451 return false;
1452 }
1453
1454 bool SyncRes::validationEnabled() const
1455 {
1456 return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
1457 }
1458
1459 uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const
1460 {
1461 uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
1462 for(const auto& record : records)
1463 lowestTTD = min(lowestTTD, record.d_ttl);
1464
1465 /* even if it was not requested for that request (Process, and neither AD nor DO set),
1466 it might be requested at a later time so we need to be careful with the TTL. */
1467 if (validationEnabled() && !signatures.empty()) {
1468 /* if we are validating, we don't want to cache records after their signatures expire. */
1469 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
1470 lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
1471
1472 for(const auto& sig : signatures) {
1473 if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
1474 // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
1475 lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
1476 }
1477 }
1478 }
1479
1480 return lowestTTD;
1481 }
1482
1483 void SyncRes::updateValidationState(vState& state, const vState stateUpdate)
1484 {
1485 LOG(d_prefix<<"validation state was "<<std::string(vStates[state])<<", state update is "<<std::string(vStates[stateUpdate]));
1486
1487 if (stateUpdate == TA) {
1488 state = Secure;
1489 }
1490 else if (stateUpdate == NTA) {
1491 state = Insecure;
1492 }
1493 else if (stateUpdate == Bogus) {
1494 state = Bogus;
1495 }
1496 else if (state == Indeterminate) {
1497 state = stateUpdate;
1498 }
1499 else if (stateUpdate == Insecure) {
1500 if (state != Bogus) {
1501 state = Insecure;
1502 }
1503 }
1504 LOG(", validation state is now "<<std::string(vStates[state])<<endl);
1505 }
1506
1507 vState SyncRes::getTA(const DNSName& zone, dsmap_t& ds)
1508 {
1509 auto luaLocal = g_luaconfs.getLocal();
1510
1511 if (luaLocal->dsAnchors.empty()) {
1512 LOG(d_prefix<<": No trust anchors configured, everything is Insecure"<<endl);
1513 /* We have no TA, everything is insecure */
1514 return Insecure;
1515 }
1516
1517 std::string reason;
1518 if (haveNegativeTrustAnchor(luaLocal->negAnchors, zone, reason)) {
1519 LOG(d_prefix<<": got NTA for '"<<zone<<"'"<<endl);
1520 return NTA;
1521 }
1522
1523 if (getTrustAnchor(luaLocal->dsAnchors, zone, ds)) {
1524 LOG(d_prefix<<": got TA for '"<<zone<<"'"<<endl);
1525 return TA;
1526 }
1527 else {
1528 LOG(d_prefix<<": no TA found for '"<<zone<<"' among "<< luaLocal->dsAnchors.size()<<endl);
1529 }
1530
1531 if (zone.isRoot()) {
1532 /* No TA for the root */
1533 return Insecure;
1534 }
1535
1536 return Indeterminate;
1537 }
1538
1539 static size_t countSupportedDS(const dsmap_t& dsmap)
1540 {
1541 size_t count = 0;
1542
1543 for (const auto& ds : dsmap) {
1544 if (isSupportedDS(ds)) {
1545 count++;
1546 }
1547 }
1548
1549 return count;
1550 }
1551
1552 vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsigned int depth, bool bogusOnNXD, bool* foundCut)
1553 {
1554 vState result = getTA(zone, ds);
1555
1556 if (result != Indeterminate || taOnly) {
1557 if (foundCut) {
1558 *foundCut = (result != Indeterminate);
1559 }
1560
1561 if (result == TA) {
1562 if (countSupportedDS(ds) == 0) {
1563 ds.clear();
1564 result = Insecure;
1565 }
1566 else {
1567 result = Secure;
1568 }
1569 }
1570 else if (result == NTA) {
1571 result = Insecure;
1572 }
1573
1574 return result;
1575 }
1576
1577 bool oldSkipCNAME = d_skipCNAMECheck;
1578 d_skipCNAMECheck = true;
1579
1580 std::set<GetBestNSAnswer> beenthere;
1581 std::vector<DNSRecord> dsrecords;
1582
1583 vState state = Indeterminate;
1584 int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state);
1585 d_skipCNAMECheck = oldSkipCNAME;
1586
1587 if (rcode == RCode::NoError || (rcode == RCode::NXDomain && !bogusOnNXD)) {
1588
1589 uint8_t bestDigestType = 0;
1590
1591 if (state == Secure) {
1592 bool gotCNAME = false;
1593 for (const auto& record : dsrecords) {
1594 if (record.d_type == QType::DS) {
1595 const auto dscontent = getRR<DSRecordContent>(record);
1596 if (dscontent && isSupportedDS(*dscontent)) {
1597 // Make GOST a lower prio than SHA256
1598 if (dscontent->d_digesttype == DNSSECKeeper::GOST && bestDigestType == DNSSECKeeper::SHA256) {
1599 continue;
1600 }
1601 if (dscontent->d_digesttype > bestDigestType || (bestDigestType == DNSSECKeeper::GOST && dscontent->d_digesttype == DNSSECKeeper::SHA256)) {
1602 bestDigestType = dscontent->d_digesttype;
1603 }
1604 ds.insert(*dscontent);
1605 }
1606 }
1607 else if (record.d_type == QType::CNAME && record.d_name == zone) {
1608 gotCNAME = true;
1609 }
1610 }
1611
1612 /* RFC 4509 section 3: "Validator implementations SHOULD ignore DS RRs containing SHA-1
1613 * digests if DS RRs with SHA-256 digests are present in the DS RRset."
1614 * As SHA348 is specified as well, the spirit of the this line is "use the best algorithm".
1615 */
1616 for (auto dsrec = ds.begin(); dsrec != ds.end(); ) {
1617 if (dsrec->d_digesttype != bestDigestType) {
1618 dsrec = ds.erase(dsrec);
1619 }
1620 else {
1621 ++dsrec;
1622 }
1623 }
1624
1625 if (rcode == RCode::NoError && ds.empty()) {
1626 if (foundCut) {
1627 if (gotCNAME || denialProvesNoDelegation(zone, dsrecords)) {
1628 /* we are still inside the same Secure zone */
1629
1630 *foundCut = false;
1631 return Secure;
1632 }
1633
1634 *foundCut = true;
1635 }
1636
1637 return Insecure;
1638 } else if (foundCut && rcode == RCode::NoError && !ds.empty()) {
1639 *foundCut = true;
1640 }
1641 }
1642
1643 return state;
1644 }
1645
1646 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1647 return Bogus;
1648 }
1649
1650 bool SyncRes::haveExactValidationStatus(const DNSName& domain)
1651 {
1652 if (!shouldValidate()) {
1653 return false;
1654 }
1655 const auto& it = d_cutStates.find(domain);
1656 if (it != d_cutStates.cend()) {
1657 return true;
1658 }
1659 return false;
1660 }
1661
1662 vState SyncRes::getValidationStatus(const DNSName& subdomain, bool allowIndeterminate)
1663 {
1664 vState result = Indeterminate;
1665
1666 if (!shouldValidate()) {
1667 return result;
1668 }
1669 DNSName name(subdomain);
1670 do {
1671 const auto& it = d_cutStates.find(name);
1672 if (it != d_cutStates.cend()) {
1673 if (allowIndeterminate || it->second != Indeterminate) {
1674 LOG(d_prefix<<": got status "<<vStates[it->second]<<" for name "<<subdomain<<" (from "<<name<<")"<<endl);
1675 return it->second;
1676 }
1677 }
1678 }
1679 while (name.chopOff());
1680
1681 return result;
1682 }
1683
1684 bool SyncRes::lookForCut(const DNSName& qname, unsigned int depth, const vState existingState, vState& newState)
1685 {
1686 bool foundCut = false;
1687 dsmap_t ds;
1688 vState dsState = getDSRecords(qname, ds, newState == Bogus || existingState == Insecure || existingState == Bogus, depth, false, &foundCut);
1689
1690 if (dsState != Indeterminate) {
1691 newState = dsState;
1692 }
1693
1694 return foundCut;
1695 }
1696
1697 void SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth)
1698 {
1699 if(!begin.isPartOf(end)) {
1700 LOG(d_prefix<<" "<<begin.toLogString()<<" is not part of "<<end.toString()<<endl);
1701 throw PDNSException(begin.toLogString() + " is not part of " + end.toString());
1702 }
1703
1704 if (d_cutStates.count(begin) != 0) {
1705 return;
1706 }
1707
1708 dsmap_t ds;
1709 vState cutState = getDSRecords(end, ds, false, depth);
1710 LOG(d_prefix<<": setting cut state for "<<end<<" to "<<vStates[cutState]<<endl);
1711 d_cutStates[end] = cutState;
1712
1713 if (!shouldValidate()) {
1714 return;
1715 }
1716
1717 DNSName qname(end);
1718 std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
1719
1720 bool oldSkipCNAME = d_skipCNAMECheck;
1721 d_skipCNAMECheck = true;
1722
1723 while(qname != begin) {
1724 if (labelsToAdd.empty())
1725 break;
1726
1727 qname.prependRawLabel(labelsToAdd.back());
1728 labelsToAdd.pop_back();
1729 LOG(d_prefix<<": - Looking for a cut at "<<qname<<endl);
1730
1731 const auto cutIt = d_cutStates.find(qname);
1732 if (cutIt != d_cutStates.cend()) {
1733 if (cutIt->second != Indeterminate) {
1734 LOG(d_prefix<<": - Cut already known at "<<qname<<endl);
1735 cutState = cutIt->second;
1736 continue;
1737 }
1738 }
1739
1740 /* no need to look for NS and DS if we are already insecure or bogus,
1741 just look for (N)TA
1742 */
1743 if (cutState == Insecure || cutState == Bogus) {
1744 dsmap_t cutDS;
1745 vState newState = getDSRecords(qname, cutDS, true, depth);
1746 if (newState == Indeterminate) {
1747 continue;
1748 }
1749
1750 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[newState]<<endl);
1751 cutState = newState;
1752
1753 d_cutStates[qname] = cutState;
1754
1755 continue;
1756 }
1757
1758 vState newState = Indeterminate;
1759 /* temporarily mark as Indeterminate, so that we won't enter an endless loop
1760 trying to determine that zone cut again. */
1761 d_cutStates[qname] = newState;
1762 bool foundCut = lookForCut(qname, depth + 1, cutState, newState);
1763 if (foundCut) {
1764 LOG(d_prefix<<": - Found cut at "<<qname<<endl);
1765 if (newState != Indeterminate) {
1766 cutState = newState;
1767 }
1768 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[cutState]<<endl);
1769 d_cutStates[qname] = cutState;
1770 }
1771 else {
1772 /* remove the temporary cut */
1773 LOG(d_prefix<<qname<<": removing cut state for "<<qname<<endl);
1774 d_cutStates.erase(qname);
1775 }
1776 }
1777
1778 d_skipCNAMECheck = oldSkipCNAME;
1779
1780 LOG(d_prefix<<": list of cuts from "<<begin<<" to "<<end<<endl);
1781 for (const auto& cut : d_cutStates) {
1782 if (cut.first.isRoot() || (begin.isPartOf(cut.first) && cut.first.isPartOf(end))) {
1783 LOG(" - "<<cut.first<<": "<<vStates[cut.second]<<endl);
1784 }
1785 }
1786 }
1787
1788 vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth)
1789 {
1790 dsmap_t ds;
1791 if (!signatures.empty()) {
1792 DNSName signer = getSigner(signatures);
1793
1794 if (!signer.empty() && zone.isPartOf(signer)) {
1795 vState state = getDSRecords(signer, ds, false, depth);
1796
1797 if (state != Secure) {
1798 return state;
1799 }
1800 }
1801 }
1802
1803 skeyset_t tentativeKeys;
1804 std::vector<shared_ptr<DNSRecordContent> > toSign;
1805
1806 for (const auto& dnskey : dnskeys) {
1807 if (dnskey.d_type == QType::DNSKEY) {
1808 auto content = getRR<DNSKEYRecordContent>(dnskey);
1809 if (content) {
1810 tentativeKeys.insert(content);
1811 toSign.push_back(content);
1812 }
1813 }
1814 }
1815
1816 LOG(d_prefix<<": trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
1817 skeyset_t validatedKeys;
1818 validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
1819
1820 LOG(d_prefix<<": we now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
1821
1822 /* if we found at least one valid RRSIG covering the set,
1823 all tentative keys are validated keys. Otherwise it means
1824 we haven't found at least one DNSKEY and a matching RRSIG
1825 covering this set, this looks Bogus. */
1826 if (validatedKeys.size() != tentativeKeys.size()) {
1827 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1828 return Bogus;
1829 }
1830
1831 return Secure;
1832 }
1833
1834 vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth)
1835 {
1836 std::vector<DNSRecord> records;
1837 std::set<GetBestNSAnswer> beenthere;
1838 LOG(d_prefix<<"Retrieving DNSKeys for "<<signer<<endl);
1839
1840 vState state = Indeterminate;
1841 /* following CNAME might lead to us to the wrong DNSKEY */
1842 bool oldSkipCNAME = d_skipCNAMECheck;
1843 d_skipCNAMECheck = true;
1844 int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state);
1845 d_skipCNAMECheck = oldSkipCNAME;
1846
1847 if (rcode == RCode::NoError) {
1848 if (state == Secure) {
1849 for (const auto& key : records) {
1850 if (key.d_type == QType::DNSKEY) {
1851 auto content = getRR<DNSKEYRecordContent>(key);
1852 if (content) {
1853 keys.insert(content);
1854 }
1855 }
1856 }
1857 }
1858 LOG(d_prefix<<"Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<vStates[state]<<endl);
1859 return state;
1860 }
1861
1862 LOG(d_prefix<<"Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
1863 return Bogus;
1864 }
1865
1866 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)
1867 {
1868 skeyset_t keys;
1869 if (!signatures.empty()) {
1870 const DNSName signer = getSigner(signatures);
1871 if (!signer.empty() && name.isPartOf(signer)) {
1872 if ((qtype == QType::DNSKEY || qtype == QType::DS) && signer == qname) {
1873 /* we are already retrieving those keys, sorry */
1874 return Indeterminate;
1875 }
1876 vState state = getDNSKeys(signer, keys, depth);
1877 if (state != Secure) {
1878 return state;
1879 }
1880 }
1881 } else {
1882 LOG(d_prefix<<"Bogus!"<<endl);
1883 return Bogus;
1884 }
1885
1886 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
1887 for (const auto& record : records) {
1888 recordcontents.push_back(record.d_content);
1889 }
1890
1891 LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
1892 if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
1893 LOG(d_prefix<<"Secure!"<<endl);
1894 return Secure;
1895 }
1896
1897 LOG(d_prefix<<"Bogus!"<<endl);
1898 return Bogus;
1899 }
1900
1901 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)
1902 {
1903 tcache_t tcache;
1904
1905 string prefix;
1906 if(doLog()) {
1907 prefix=d_prefix;
1908 prefix.append(depth, ' ');
1909 }
1910
1911 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
1912 const unsigned int labelCount = qname.countLabels();
1913 bool isCNAMEAnswer = false;
1914 for(const auto& rec : lwr.d_records) {
1915 if (rec.d_class != QClass::IN) {
1916 continue;
1917 }
1918
1919 if(!isCNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
1920 isCNAMEAnswer = true;
1921 }
1922
1923 /* if we have a positive answer synthetized from a wildcard,
1924 we need to store the corresponding NSEC/NSEC3 records proving
1925 that the exact name did not exist in the negative cache */
1926 if(needWildcardProof) {
1927 if (nsecTypes.count(rec.d_type)) {
1928 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1929 }
1930 else if (rec.d_type == QType::RRSIG) {
1931 auto rrsig = getRR<RRSIGRecordContent>(rec);
1932 if (rrsig && nsecTypes.count(rrsig->d_type)) {
1933 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1934 }
1935 }
1936 }
1937 if(rec.d_type == QType::RRSIG) {
1938 auto rrsig = getRR<RRSIGRecordContent>(rec);
1939 if (rrsig) {
1940 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
1941 count can be lower than the name's label count if it was
1942 synthetized from the wildcard. Note that the difference might
1943 be > 1. */
1944 if (rec.d_name == qname && rrsig->d_labels < labelCount) {
1945 LOG(prefix<<qname<<": RRSIG indicates the name was synthetized from a wildcard, we need a wildcard proof"<<endl);
1946 needWildcardProof = true;
1947 wildcardLabelsCount = rrsig->d_labels;
1948 }
1949
1950 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
1951 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
1952 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);
1953 }
1954 }
1955 }
1956
1957 // reap all answers from this packet that are acceptable
1958 for(auto& rec : lwr.d_records) {
1959 if(rec.d_type == QType::OPT) {
1960 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
1961 continue;
1962 }
1963 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<<" ");
1964 if(rec.d_type == QType::ANY) {
1965 LOG("NO! - we don't accept 'ANY'-typed data"<<endl);
1966 continue;
1967 }
1968
1969 if(rec.d_class != QClass::IN) {
1970 LOG("NO! - we don't accept records for any other class than 'IN'"<<endl);
1971 continue;
1972 }
1973
1974 if(rec.d_name.isPartOf(auth)) {
1975 if(rec.d_type == QType::RRSIG) {
1976 LOG("RRSIG - separate"<<endl);
1977 }
1978 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)) {
1979 LOG("NO! Is from delegation-only zone"<<endl);
1980 s_nodelegated++;
1981 return RCode::NXDomain;
1982 }
1983 else {
1984 bool haveLogged = false;
1985 if (!t_sstorage.domainmap->empty()) {
1986 // Check if we are authoritative for a zone in this answer
1987 DNSName tmp_qname(rec.d_name);
1988 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
1989 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
1990 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
1991 if (auth_domain_iter->first != auth) {
1992 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
1993 continue;
1994 } else {
1995 LOG("YES! - This answer was ");
1996 if (!wasForwarded) {
1997 LOG("retrieved from the local auth store.");
1998 } else {
1999 LOG("received from a server we forward to.");
2000 }
2001 haveLogged = true;
2002 LOG(endl);
2003 }
2004 }
2005 }
2006 if (!haveLogged) {
2007 LOG("YES!"<<endl);
2008 }
2009
2010 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
2011
2012 DNSRecord dr(rec);
2013 dr.d_ttl += d_now.tv_sec;
2014 dr.d_place=DNSResourceRecord::ANSWER;
2015 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
2016 }
2017 }
2018 else
2019 LOG("NO!"<<endl);
2020 }
2021
2022 // supplant
2023 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2024 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)
2025 uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
2026
2027 for(auto& record : i->second.records)
2028 record.d_ttl = lowestTTD; // boom
2029 }
2030
2031 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
2032 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
2033 }
2034
2035 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2036
2037 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
2038 continue;
2039
2040 /* Even if the AA bit is set, additional data cannot be considered
2041 as authoritative. This is especially important during validation
2042 because keeping records in the additional section is allowed even
2043 if the corresponding RRSIGs are not included, without setting the TC
2044 bit, as stated in rfc4035's section 3.1.1. Including RRSIG RRs in a Response:
2045 "When placing a signed RRset in the Additional section, the name
2046 server MUST also place its RRSIG RRs in the Additional section.
2047 If space does not permit inclusion of both the RRset and its
2048 associated RRSIG RRs, the name server MAY retain the RRset while
2049 dropping the RRSIG RRs. If this happens, the name server MUST NOT
2050 set the TC bit solely because these RRSIG RRs didn't fit."
2051 */
2052 bool isAA = lwr.d_aabit && i->first.place != DNSResourceRecord::ADDITIONAL;
2053 if (isAA && isCNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER || i->first.type != QType::CNAME)) {
2054 /*
2055 rfc2181 states:
2056 Note that the answer section of an authoritative answer normally
2057 contains only authoritative data. However when the name sought is an
2058 alias (see section 10.1.1) only the record describing that alias is
2059 necessarily authoritative. Clients should assume that other records
2060 may have come from the server's cache. Where authoritative answers
2061 are required, the client should query again, using the canonical name
2062 associated with the alias.
2063 */
2064 isAA = false;
2065 }
2066
2067 vState recordState = getValidationStatus(i->first.name, false);
2068 LOG(d_prefix<<": got initial zone status "<<vStates[recordState]<<" for record "<<i->first.name<<endl);
2069
2070 if (shouldValidate() && recordState == Secure) {
2071 vState initialState = recordState;
2072
2073 if (isAA) {
2074 if (i->first.place != DNSResourceRecord::ADDITIONAL) {
2075 /* the additional entries can be insecure,
2076 like glue:
2077 "Glue address RRsets associated with delegations MUST NOT be signed"
2078 */
2079 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) {
2080 LOG(d_prefix<<"Validating DNSKEY for "<<i->first.name<<endl);
2081 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth);
2082 }
2083 else {
2084 LOG(d_prefix<<"Validating non-additional record for "<<i->first.name<<endl);
2085 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2086 /* 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 */
2087 if (qtype == QType::NS && i->second.signatures.empty() && recordState == Bogus && haveExactValidationStatus(i->first.name) && getValidationStatus(i->first.name) == Indeterminate) {
2088 recordState = Indeterminate;
2089 }
2090 }
2091 }
2092 }
2093 else {
2094 /* in a non authoritative answer, we only care about the DS record (or lack of) */
2095 if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
2096 LOG(d_prefix<<"Validating DS record for "<<i->first.name<<endl);
2097 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2098 }
2099 }
2100
2101 if (initialState == Secure && state != recordState) {
2102 updateValidationState(state, recordState);
2103 }
2104 }
2105 else {
2106 if (shouldValidate()) {
2107 LOG(d_prefix<<"Skipping validation because the current state is "<<vStates[recordState]<<endl);
2108 }
2109 }
2110
2111 /* We don't need to store NSEC3 records in the positive cache because:
2112 - we don't allow direct NSEC3 queries
2113 - denial of existence proofs in wildcard expanded positive responses are stored in authorityRecs
2114 - denial of existence proofs for negative responses are stored in the negative cache
2115 */
2116 if (i->first.type != QType::NSEC3) {
2117 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);
2118 }
2119
2120 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
2121 d_wasVariable=true;
2122 }
2123
2124 return RCode::NoError;
2125 }
2126
2127 void SyncRes::updateDenialValidationState(NegCache::NegCacheEntry& ne, vState& state, const dState denialState, const dState expectedState, bool allowOptOut)
2128 {
2129 if (denialState == expectedState) {
2130 ne.d_validationState = Secure;
2131 }
2132 else {
2133 if (denialState == OPTOUT && allowOptOut) {
2134 LOG(d_prefix<<"OPT-out denial found for "<<ne.d_name<<endl);
2135 ne.d_validationState = Secure;
2136 return;
2137 }
2138 else if (denialState == INSECURE) {
2139 LOG(d_prefix<<"Insecure denial found for "<<ne.d_name<<", returning Insecure"<<endl);
2140 ne.d_validationState = Insecure;
2141 }
2142 else {
2143 LOG(d_prefix<<"Invalid denial found for "<<ne.d_name<<", returning Bogus, res="<<denialState<<", expectedState="<<expectedState<<endl);
2144 ne.d_validationState = Bogus;
2145 }
2146 updateValidationState(state, ne.d_validationState);
2147 }
2148 }
2149
2150 dState SyncRes::getDenialValidationState(NegCache::NegCacheEntry& ne, const vState state, const dState expectedState, bool referralToUnsigned)
2151 {
2152 cspmap_t csp = harvestCSPFromNE(ne);
2153 return getDenial(csp, ne.d_name, ne.d_qtype.getCode(), referralToUnsigned, expectedState == NXQTYPE);
2154 }
2155
2156 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)
2157 {
2158 bool done = false;
2159
2160 for(auto& rec : lwr.d_records) {
2161 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
2162 continue;
2163
2164 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2165 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
2166 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
2167
2168 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
2169 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
2170 ret.push_back(rec);
2171
2172 NegCache::NegCacheEntry ne;
2173
2174 uint32_t lowestTTL = rec.d_ttl;
2175 /* if we get an NXDomain answer with a CNAME, the name
2176 does exist but the target does not */
2177 ne.d_name = newtarget.empty() ? qname : newtarget;
2178 ne.d_qtype = QType(0); // this encodes 'whole record'
2179 ne.d_auth = rec.d_name;
2180 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2181 ne.d_ttd = d_now.tv_sec + lowestTTL;
2182
2183 if (state == Secure) {
2184 dState denialState = getDenialValidationState(ne, state, NXDOMAIN, false);
2185 updateDenialValidationState(ne, state, denialState, NXDOMAIN, false);
2186 }
2187 else {
2188 ne.d_validationState = state;
2189 }
2190
2191 /* if we get an NXDomain answer with a CNAME, let's not cache the
2192 target, even the server was authoritative for it,
2193 and do an additional query for the CNAME target.
2194 We have a regression test making sure we do exactly that.
2195 */
2196 if(!wasVariable() && newtarget.empty()) {
2197 t_sstorage.negcache.add(ne);
2198 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
2199 ne.d_name = ne.d_name.getLastLabel();
2200 t_sstorage.negcache.add(ne);
2201 }
2202 }
2203
2204 negindic=true;
2205 }
2206 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
2207 ret.push_back(rec);
2208 if (auto content = getRR<CNAMERecordContent>(rec)) {
2209 newtarget=content->getTarget();
2210 }
2211 }
2212 /* if we have a positive answer synthetized from a wildcard, we need to
2213 return the corresponding NSEC/NSEC3 records from the AUTHORITY section
2214 proving that the exact name did not exist */
2215 else if(needWildcardProof && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::AUTHORITY) {
2216 ret.push_back(rec); // enjoy your DNSSEC
2217 }
2218 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
2219 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
2220 (
2221 rec.d_type==qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType(QType::ANY))
2222 )
2223 )
2224 {
2225 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
2226
2227 done=true;
2228 ret.push_back(rec);
2229
2230 if (state == Secure && needWildcardProof) {
2231 /* We have a positive answer synthetized from a wildcard, we need to check that we have
2232 proof that the exact name doesn't exist so the wildcard can be used,
2233 as described in section 5.3.4 of RFC 4035 and 5.3 of FRC 7129.
2234 */
2235 NegCache::NegCacheEntry ne;
2236
2237 uint32_t lowestTTL = rec.d_ttl;
2238 ne.d_name = qname;
2239 ne.d_qtype = QType(0); // this encodes 'whole record'
2240 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2241
2242 cspmap_t csp = harvestCSPFromNE(ne);
2243 dState res = getDenial(csp, qname, ne.d_qtype.getCode(), false, false, false, wildcardLabelsCount);
2244 if (res != NXDOMAIN) {
2245 vState st = Bogus;
2246 if (res == INSECURE) {
2247 /* Some part could not be validated, for example a NSEC3 record with a too large number of iterations,
2248 this is not enough to warrant a Bogus, but go Insecure. */
2249 st = Insecure;
2250 LOG(d_prefix<<"Unable to validate denial in wildcard expanded positive response found for "<<qname<<", returning Insecure, res="<<res<<endl);
2251 }
2252 else {
2253 LOG(d_prefix<<"Invalid denial in wildcard expanded positive response found for "<<qname<<", returning Bogus, res="<<res<<endl);
2254 }
2255
2256 updateValidationState(state, st);
2257 /* we already stored the record with a different validation status, let's fix it */
2258 t_RC->updateValidationStatus(d_now.tv_sec, qname, qtype, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, lwr.d_aabit, st);
2259 }
2260 }
2261 }
2262 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER) {
2263 if(rec.d_type != QType::RRSIG || rec.d_name == qname)
2264 ret.push_back(rec); // enjoy your DNSSEC
2265 }
2266 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::NS && qname.isPartOf(rec.d_name)) {
2267 if(moreSpecificThan(rec.d_name,auth)) {
2268 newauth=rec.d_name;
2269 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2270 realreferral=true;
2271 }
2272 else {
2273 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
2274 }
2275 if (auto content = getRR<NSRecordContent>(rec)) {
2276 nsset.insert(content->getNS());
2277 }
2278 }
2279 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
2280 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2281 }
2282 else if(realreferral && rec.d_place==DNSResourceRecord::AUTHORITY && (rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && newauth.isPartOf(auth)) {
2283 /* we might have received a denial of the DS, let's check */
2284 if (state == Secure) {
2285 NegCache::NegCacheEntry ne;
2286 ne.d_auth = auth;
2287 ne.d_name = newauth;
2288 ne.d_qtype = QType::DS;
2289 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2290 uint32_t lowestTTL = rec.d_ttl;
2291 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2292
2293 dState denialState = getDenialValidationState(ne, state, NXQTYPE, true);
2294
2295 if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
2296 ne.d_ttd = lowestTTL + d_now.tv_sec;
2297 ne.d_validationState = Secure;
2298 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
2299
2300 if(!wasVariable()) {
2301 t_sstorage.negcache.add(ne);
2302 }
2303
2304 if (qname == newauth && qtype == QType::DS) {
2305 /* we are actually done! */
2306 negindic=true;
2307 nsset.clear();
2308 }
2309 }
2310 }
2311 }
2312 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2313 lwr.d_rcode==RCode::NoError && qname.isPartOf(rec.d_name)) {
2314 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
2315
2316 if(!newtarget.empty()) {
2317 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
2318 }
2319 else {
2320 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2321 ret.push_back(rec);
2322
2323 NegCache::NegCacheEntry ne;
2324 ne.d_auth = rec.d_name;
2325 uint32_t lowestTTL = rec.d_ttl;
2326 ne.d_name = qname;
2327 ne.d_qtype = qtype;
2328 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2329 ne.d_ttd = d_now.tv_sec + lowestTTL;
2330
2331 if (state == Secure) {
2332 dState denialState = getDenialValidationState(ne, state, NXQTYPE, false);
2333 updateDenialValidationState(ne, state, denialState, NXQTYPE, qtype == QType::DS);
2334 } else {
2335 ne.d_validationState = state;
2336 }
2337
2338 if(!wasVariable()) {
2339 if(qtype.getCode()) { // prevents us from blacking out a whole domain
2340 t_sstorage.negcache.add(ne);
2341 }
2342 }
2343 negindic=true;
2344 }
2345 }
2346 }
2347
2348 return done;
2349 }
2350
2351 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)
2352 {
2353 int resolveret;
2354 s_outqueries++;
2355 d_outqueries++;
2356
2357 if(d_outqueries + d_throttledqueries > s_maxqperq) {
2358 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
2359 }
2360
2361 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
2362 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");
2363 }
2364
2365 if(doTCP) {
2366 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
2367 s_tcpoutqueries++;
2368 d_tcpoutqueries++;
2369 }
2370
2371 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
2372 LOG(prefix<<qname<<": query handled by Lua"<<endl);
2373 }
2374 else {
2375 ednsmask=getEDNSSubnetMask(d_requestor, qname, remoteIP);
2376 if(ednsmask) {
2377 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
2378 s_ecsqueries++;
2379 }
2380 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(),
2381 doTCP, sendRDQuery, &d_now, ednsmask, &lwr); // <- we go out on the wire!
2382 if(ednsmask) {
2383 s_ecsresponses++;
2384 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
2385 }
2386 }
2387
2388 /* preoutquery killed the query by setting dq.rcode to -3 */
2389 if(resolveret==-3) {
2390 throw ImmediateServFailException("Query killed by policy");
2391 }
2392
2393 d_totUsec += lwr.d_usec;
2394 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
2395
2396 if(resolveret != 1) {
2397 /* Error while resolving */
2398 if(resolveret == 0) {
2399 /* Time out */
2400
2401 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
2402 d_timeouts++;
2403 s_outgoingtimeouts++;
2404
2405 if(remoteIP.sin4.sin_family == AF_INET)
2406 s_outgoing4timeouts++;
2407 else
2408 s_outgoing6timeouts++;
2409 }
2410 else if(resolveret == -2) {
2411 /* OS resource limit reached */
2412 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
2413 g_stats.resourceLimits++;
2414 }
2415 else {
2416 /* -1 means server unreachable */
2417 s_unreachables++;
2418 d_unreachables++;
2419 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
2420 }
2421
2422 if(resolveret != -2) { // don't account for resource limits, they are our own fault
2423 t_sstorage.nsSpeeds[nsName].submit(remoteIP, 1000000, &d_now); // 1 sec
2424
2425 // code below makes sure we don't filter COM or the root
2426 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) {
2427 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
2428 // mark server as down
2429 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
2430 }
2431 else if (resolveret == -1) {
2432 // unreachable, 1 minute or 100 queries
2433 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
2434 }
2435 else {
2436 // timeout
2437 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
2438 }
2439 }
2440
2441 return false;
2442 }
2443
2444 /* we got an answer */
2445 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
2446 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
2447 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2448 return false;
2449 }
2450
2451 /* this server sent a valid answer, mark it backup up if it was down */
2452 if(s_serverdownmaxfails > 0) {
2453 t_sstorage.fails.clear(remoteIP);
2454 }
2455
2456 if(lwr.d_tcbit) {
2457 *truncated = true;
2458
2459 if (doTCP) {
2460 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
2461 /* let's treat that as a ServFail answer from this server */
2462 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2463 return false;
2464 }
2465
2466 return true;
2467 }
2468
2469 return true;
2470 }
2471
2472 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)
2473 {
2474 string prefix;
2475 if(doLog()) {
2476 prefix=d_prefix;
2477 prefix.append(depth, ' ');
2478 }
2479
2480 if(s_minimumTTL) {
2481 for(auto& rec : lwr.d_records) {
2482 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
2483 }
2484 }
2485
2486 bool needWildcardProof = false;
2487 unsigned int wildcardLabelsCount;
2488 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, needWildcardProof, wildcardLabelsCount);
2489 if (*rcode != RCode::NoError) {
2490 return true;
2491 }
2492
2493 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
2494
2495 set<DNSName> nsset;
2496 bool realreferral=false, negindic=false;
2497 DNSName newauth;
2498 DNSName newtarget;
2499
2500 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof, wildcardLabelsCount);
2501
2502 if(done){
2503 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
2504 LOG(prefix<<qname<<": validation status is "<<vStates[state]<<endl);
2505 *rcode = RCode::NoError;
2506 return true;
2507 }
2508
2509 if(!newtarget.empty()) {
2510 if(newtarget == qname) {
2511 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
2512 *rcode = RCode::ServFail;
2513 return true;
2514 }
2515
2516 if(depth > 10) {
2517 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
2518 *rcode = RCode::ServFail;
2519 return true;
2520 }
2521
2522 if (qtype == QType::DS) {
2523 LOG(prefix<<qname<<": status=got a CNAME referral, but we are looking for a DS"<<endl);
2524
2525 if(d_doDNSSEC)
2526 addNXNSECS(ret, lwr.d_records);
2527
2528 *rcode = RCode::NoError;
2529 return true;
2530 }
2531 else {
2532 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
2533
2534 set<GetBestNSAnswer> beenthere2;
2535 vState cnameState = Indeterminate;
2536 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState);
2537 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
2538 updateValidationState(state, cnameState);
2539 return true;
2540 }
2541 }
2542
2543 if(lwr.d_rcode == RCode::NXDomain) {
2544 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
2545
2546 if(d_doDNSSEC)
2547 addNXNSECS(ret, lwr.d_records);
2548
2549 *rcode = RCode::NXDomain;
2550 return true;
2551 }
2552
2553 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
2554 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
2555
2556 if(state == Secure && lwr.d_aabit && !negindic) {
2557 updateValidationState(state, Bogus);
2558 }
2559
2560 if(d_doDNSSEC)
2561 addNXNSECS(ret, lwr.d_records);
2562
2563 *rcode = RCode::NoError;
2564 return true;
2565 }
2566
2567 if(realreferral) {
2568 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
2569
2570 nameservers.clear();
2571 for (auto const &nameserver : nsset) {
2572 if (d_wantsRPZ) {
2573 d_appliedPolicy = dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
2574 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2575 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
2576 *rcode = -2;
2577 return true;
2578 }
2579 }
2580 nameservers.insert({nameserver, {{}, false}});
2581 }
2582 LOG("looping to them"<<endl);
2583 *gotNewServers = true;
2584 auth=newauth;
2585
2586 return false;
2587 }
2588
2589 return false;
2590 }
2591
2592 /** returns:
2593 * -1 in case of no results
2594 * -2 when a FilterEngine Policy was hit
2595 * rcode otherwise
2596 */
2597 int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
2598 vector<DNSRecord>&ret,
2599 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state)
2600 {
2601 auto luaconfsLocal = g_luaconfs.getLocal();
2602 string prefix;
2603 if(doLog()) {
2604 prefix=d_prefix;
2605 prefix.append(depth, ' ');
2606 }
2607
2608 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
2609
2610 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
2611 return -2;
2612 }
2613
2614 LOG(endl);
2615
2616 for(;;) { // we may get more specific nameservers
2617 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
2618
2619 for(auto tns=rnameservers.cbegin();;++tns) {
2620 if(tns==rnameservers.cend()) {
2621 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
2622 if(!auth.isRoot() && flawedNSSet) {
2623 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
2624
2625 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
2626 g_stats.nsSetInvalidations++;
2627 }
2628 return -1;
2629 }
2630
2631 bool cacheOnly = false;
2632 // this line needs to identify the 'self-resolving' behaviour
2633 if(qname == *tns && (qtype.getCode() == QType::A || qtype.getCode() == QType::AAAA)) {
2634 /* we might have a glue entry in cache so let's try this NS
2635 but only if we have enough in the cache to know how to reach it */
2636 LOG(prefix<<qname<<": Using NS to resolve itself, but only using what we have in cache ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
2637 cacheOnly = true;
2638 }
2639
2640 typedef vector<ComboAddress> remoteIPs_t;
2641 remoteIPs_t remoteIPs;
2642 remoteIPs_t::const_iterator remoteIP;
2643 bool pierceDontQuery=false;
2644 bool sendRDQuery=false;
2645 boost::optional<Netmask> ednsmask;
2646 LWResult lwr;
2647 const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty());
2648 int rcode = RCode::NoError;
2649 bool gotNewServers = false;
2650
2651 if(tns->empty() && !wasForwarded) {
2652 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
2653 /* setting state to indeterminate since validation is disabled for local auth zone,
2654 and Insecure would be misleading. */
2655 state = Indeterminate;
2656 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
2657 lwr.d_tcbit=false;
2658 lwr.d_aabit=true;
2659
2660 /* we have received an answer, are we done ? */
2661 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
2662 if (done) {
2663 return rcode;
2664 }
2665 if (gotNewServers) {
2666 break;
2667 }
2668 }
2669 else {
2670 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
2671 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly);
2672
2673 if(remoteIPs.empty()) {
2674 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
2675 flawedNSSet=true;
2676 continue;
2677 }
2678 else {
2679 bool hitPolicy{false};
2680 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
2681 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2682 if(remoteIP != remoteIPs.cbegin()) {
2683 LOG(", ");
2684 }
2685 LOG(remoteIP->toString());
2686 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
2687 hitPolicy = true;
2688 }
2689 }
2690 LOG(endl);
2691 if (hitPolicy) //implies d_wantsRPZ
2692 return -2;
2693 }
2694
2695 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2696 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
2697
2698 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
2699 continue;
2700 }
2701
2702 bool truncated = false;
2703 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2704 *tns, *remoteIP, false, &truncated);
2705 if (gotAnswer && truncated ) {
2706 /* retry, over TCP this time */
2707 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2708 *tns, *remoteIP, true, &truncated);
2709 }
2710
2711 if (!gotAnswer) {
2712 continue;
2713 }
2714
2715 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);
2716
2717 /* // for you IPv6 fanatics :-)
2718 if(remoteIP->sin4.sin_family==AF_INET6)
2719 lwr.d_usec/=3;
2720 */
2721 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
2722
2723 t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
2724
2725 /* we have received an answer, are we done ? */
2726 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
2727 if (done) {
2728 return rcode;
2729 }
2730 if (gotNewServers) {
2731 break;
2732 }
2733 /* was lame */
2734 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
2735 }
2736
2737 if (gotNewServers) {
2738 break;
2739 }
2740
2741 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
2742 continue;
2743
2744 }
2745 }
2746 }
2747 return -1;
2748 }
2749
2750 void SyncRes::setIncomingECS(boost::optional<const EDNSSubnetOpts&> incomingECS)
2751 {
2752 d_incomingECS = incomingECS;
2753 if (incomingECS) {
2754 if (d_incomingECS->source.getBits() == 0) {
2755 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0.
2756 But using an empty ECS in that case would mean inserting
2757 a non ECS-specific entry into the cache, preventing any further
2758 ECS-specific query to be sent.
2759 So instead we use the trick described in section 7.1.2:
2760 "The subsequent Recursive Resolver query to the Authoritative Nameserver
2761 will then either not include an ECS option or MAY optionally include
2762 its own address information, which is what the Authoritative
2763 Nameserver will almost certainly use to generate any Tailored
2764 Response in lieu of an option. This allows the answer to be handled
2765 by the same caching mechanism as other queries, with an explicit
2766 indicator of the applicable scope. Subsequent Stub Resolver queries
2767 for /0 can then be answered from this cached response.
2768 */
2769 d_incomingECS = s_ecsScopeZero;
2770 d_incomingECSNetwork = s_ecsScopeZero.source.getMaskedNetwork();
2771 }
2772 else {
2773 uint8_t bits = std::min(incomingECS->source.getBits(), (incomingECS->source.isIpv4() ? s_ecsipv4limit : s_ecsipv6limit));
2774 d_incomingECS->source = Netmask(incomingECS->source.getNetwork(), bits);
2775 d_incomingECSNetwork = d_incomingECS->source.getMaskedNetwork();
2776 }
2777 }
2778 else {
2779 d_incomingECSNetwork = ComboAddress();
2780 }
2781 }
2782
2783 boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem)
2784 {
2785 boost::optional<Netmask> result;
2786 ComboAddress trunc;
2787 uint8_t bits;
2788 if(d_incomingECSFound) {
2789 trunc = d_incomingECSNetwork;
2790 bits = d_incomingECS->source.getBits();
2791 }
2792 else if(!local.isIPv4() || local.sin4.sin_addr.s_addr) { // detect unset 'requestor'
2793 trunc = local;
2794 bits = local.isIPv4() ? 32 : 128;
2795 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
2796 }
2797 else {
2798 /* nothing usable */
2799 return result;
2800 }
2801
2802 if(s_ednsdomains.check(dn) || s_ednssubnets.match(rem)) {
2803 trunc.truncate(bits);
2804 return boost::optional<Netmask>(Netmask(trunc, bits));
2805 }
2806
2807 return result;
2808 }
2809
2810 void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
2811 {
2812 vector<string> parts;
2813 stringtok(parts, wlist, ",; ");
2814 for(const auto& a : parts) {
2815 try {
2816 s_ednssubnets.addMask(Netmask(a));
2817 }
2818 catch(...) {
2819 s_ednsdomains.add(DNSName(a));
2820 }
2821 }
2822 }
2823
2824 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
2825 int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
2826 {
2827 struct timeval now;
2828 gettimeofday(&now, 0);
2829
2830 SyncRes sr(now);
2831 int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
2832
2833 return res;
2834 }
2835
2836 int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
2837 SyncRes sr(now);
2838 sr.setDoEDNS0(true);
2839 sr.setUpdatingRootNS();
2840 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
2841 sr.setDNSSECValidationRequested(g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate);
2842 sr.setAsyncCallback(asyncCallback);
2843
2844 vector<DNSRecord> ret;
2845 int res=-1;
2846 try {
2847 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
2848 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
2849 auto state = sr.getValidationState();
2850 if (state == Bogus)
2851 throw PDNSException("Got Bogus validation result for .|NS");
2852 }
2853 return res;
2854 }
2855 catch(const PDNSException& e) {
2856 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2857 }
2858 catch(const ImmediateServFailException& e) {
2859 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2860 }
2861 catch(const std::exception& e) {
2862 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
2863 }
2864 catch(...) {
2865 L<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
2866 }
2867
2868 if(!res) {
2869 L<<Logger::Notice<<"Refreshed . records"<<endl;
2870 }
2871 else
2872 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
2873
2874 return res;
2875 }