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