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