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