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