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