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