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