]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/syncres.cc
Merge pull request #5968 from pieterlexis/api-rectify-transaction
[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 (auto dsrec = ds.begin(); dsrec != ds.end(); ) {
1594 if (dsrec->d_digesttype != bestDigestType) {
1595 dsrec = ds.erase(dsrec);
1596 }
1597 else {
1598 ++dsrec;
1599 }
1600 }
1601
1602 if (rcode == RCode::NoError && ds.empty()) {
1603 if (foundCut) {
1604 if (gotCNAME || denialProvesNoDelegation(zone, dsrecords)) {
1605 /* we are still inside the same Secure zone */
1606
1607 *foundCut = false;
1608 return Secure;
1609 }
1610
1611 *foundCut = true;
1612 }
1613
1614 return Insecure;
1615 } else if (foundCut && rcode == RCode::NoError && !ds.empty()) {
1616 *foundCut = true;
1617 }
1618 }
1619
1620 return state;
1621 }
1622
1623 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1624 return Bogus;
1625 }
1626
1627 bool SyncRes::haveExactValidationStatus(const DNSName& domain)
1628 {
1629 if (!d_DNSSECValidationRequested) {
1630 return false;
1631 }
1632 const auto& it = d_cutStates.find(domain);
1633 if (it != d_cutStates.cend()) {
1634 return true;
1635 }
1636 return false;
1637 }
1638
1639 vState SyncRes::getValidationStatus(const DNSName& subdomain, bool allowIndeterminate)
1640 {
1641 vState result = Indeterminate;
1642
1643 if (!d_DNSSECValidationRequested) {
1644 return result;
1645 }
1646 DNSName name(subdomain);
1647 do {
1648 const auto& it = d_cutStates.find(name);
1649 if (it != d_cutStates.cend()) {
1650 if (allowIndeterminate || it->second != Indeterminate) {
1651 LOG(d_prefix<<": got status "<<vStates[it->second]<<" for name "<<subdomain<<" (from "<<name<<")"<<endl);
1652 return it->second;
1653 }
1654 }
1655 }
1656 while (name.chopOff());
1657
1658 return result;
1659 }
1660
1661 bool SyncRes::lookForCut(const DNSName& qname, unsigned int depth, const vState existingState, vState& newState)
1662 {
1663 bool foundCut = false;
1664 dsmap_t ds;
1665 vState dsState = getDSRecords(qname, ds, newState == Bogus || existingState == Insecure || existingState == Bogus, depth, false, &foundCut);
1666
1667 if (dsState != Indeterminate) {
1668 newState = dsState;
1669 }
1670
1671 return foundCut;
1672 }
1673
1674 void SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth)
1675 {
1676 if(!begin.isPartOf(end)) {
1677 LOG(d_prefix<<" "<<begin.toLogString()<<" is not part of "<<end.toString()<<endl);
1678 throw PDNSException(begin.toLogString() + " is not part of " + end.toString());
1679 }
1680
1681 if (d_cutStates.count(begin) != 0) {
1682 return;
1683 }
1684
1685 dsmap_t ds;
1686 vState cutState = getDSRecords(end, ds, false, depth);
1687 LOG(d_prefix<<": setting cut state for "<<end<<" to "<<vStates[cutState]<<endl);
1688 d_cutStates[end] = cutState;
1689
1690 if (!d_DNSSECValidationRequested) {
1691 return;
1692 }
1693
1694 DNSName qname(end);
1695 std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
1696
1697 bool oldSkipCNAME = d_skipCNAMECheck;
1698 d_skipCNAMECheck = true;
1699
1700 while(qname != begin) {
1701 if (labelsToAdd.empty())
1702 break;
1703
1704 qname.prependRawLabel(labelsToAdd.back());
1705 labelsToAdd.pop_back();
1706 LOG(d_prefix<<": - Looking for a cut at "<<qname<<endl);
1707
1708 const auto cutIt = d_cutStates.find(qname);
1709 if (cutIt != d_cutStates.cend()) {
1710 if (cutIt->second != Indeterminate) {
1711 LOG(d_prefix<<": - Cut already known at "<<qname<<endl);
1712 cutState = cutIt->second;
1713 continue;
1714 }
1715 }
1716
1717 /* no need to look for NS and DS if we are already insecure or bogus,
1718 just look for (N)TA
1719 */
1720 if (cutState == Insecure || cutState == Bogus) {
1721 dsmap_t cutDS;
1722 vState newState = getDSRecords(qname, cutDS, true, depth);
1723 if (newState == Indeterminate) {
1724 continue;
1725 }
1726
1727 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[newState]<<endl);
1728 cutState = newState;
1729
1730 d_cutStates[qname] = cutState;
1731
1732 continue;
1733 }
1734
1735 vState newState = Indeterminate;
1736 /* temporarily mark as Indeterminate, so that we won't enter an endless loop
1737 trying to determine that zone cut again. */
1738 d_cutStates[qname] = newState;
1739 bool foundCut = lookForCut(qname, depth + 1, cutState, newState);
1740 if (foundCut) {
1741 LOG(d_prefix<<": - Found cut at "<<qname<<endl);
1742 if (newState != Indeterminate) {
1743 cutState = newState;
1744 }
1745 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[cutState]<<endl);
1746 d_cutStates[qname] = cutState;
1747 }
1748 else {
1749 /* remove the temporary cut */
1750 LOG(d_prefix<<qname<<": removing cut state for "<<qname<<", was "<<vStates[d_cutStates[qname]]<<endl);
1751 d_cutStates.erase(qname);
1752 }
1753 }
1754
1755 d_skipCNAMECheck = oldSkipCNAME;
1756
1757 LOG(d_prefix<<": list of cuts from "<<begin<<" to "<<end<<endl);
1758 for (const auto& cut : d_cutStates) {
1759 if (cut.first.isRoot() || (begin.isPartOf(cut.first) && cut.first.isPartOf(end))) {
1760 LOG(" - "<<cut.first<<": "<<vStates[cut.second]<<endl);
1761 }
1762 }
1763 }
1764
1765 vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth)
1766 {
1767 dsmap_t ds;
1768 if (!signatures.empty()) {
1769 DNSName signer = getSigner(signatures);
1770
1771 if (!signer.empty() && signer.isPartOf(zone)) {
1772 vState state = getDSRecords(signer, ds, false, depth);
1773
1774 if (state != Secure) {
1775 return state;
1776 }
1777 }
1778 }
1779
1780 skeyset_t tentativeKeys;
1781 std::vector<shared_ptr<DNSRecordContent> > toSign;
1782
1783 for (const auto& dnskey : dnskeys) {
1784 if (dnskey.d_type == QType::DNSKEY) {
1785 auto content = getRR<DNSKEYRecordContent>(dnskey);
1786 if (content) {
1787 tentativeKeys.insert(content);
1788 toSign.push_back(content);
1789 }
1790 }
1791 }
1792
1793 LOG(d_prefix<<": trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
1794 skeyset_t validatedKeys;
1795 validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
1796
1797 LOG(d_prefix<<": we now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
1798
1799 /* if we found at least one valid RRSIG covering the set,
1800 all tentative keys are validated keys. Otherwise it means
1801 we haven't found at least one DNSKEY and a matching RRSIG
1802 covering this set, this looks Bogus. */
1803 if (validatedKeys.size() != tentativeKeys.size()) {
1804 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1805 return Bogus;
1806 }
1807
1808 return Secure;
1809 }
1810
1811 vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth)
1812 {
1813 std::vector<DNSRecord> records;
1814 std::set<GetBestNSAnswer> beenthere;
1815 LOG(d_prefix<<"Retrieving DNSKeys for "<<signer<<endl);
1816
1817 vState state = Indeterminate;
1818 /* following CNAME might lead to us to the wrong DNSKEY */
1819 bool oldSkipCNAME = d_skipCNAMECheck;
1820 d_skipCNAMECheck = true;
1821 int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state);
1822 d_skipCNAMECheck = oldSkipCNAME;
1823
1824 if (rcode == RCode::NoError) {
1825 if (state == Secure) {
1826 for (const auto& key : records) {
1827 if (key.d_type == QType::DNSKEY) {
1828 auto content = getRR<DNSKEYRecordContent>(key);
1829 if (content) {
1830 keys.insert(content);
1831 }
1832 }
1833 }
1834 }
1835 LOG(d_prefix<<"Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<vStates[state]<<endl);
1836 return state;
1837 }
1838
1839 LOG(d_prefix<<"Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
1840 return Bogus;
1841 }
1842
1843 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)
1844 {
1845 skeyset_t keys;
1846 if (!signatures.empty()) {
1847 const DNSName signer = getSigner(signatures);
1848 if (!signer.empty() && name.isPartOf(signer)) {
1849 if ((qtype == QType::DNSKEY || qtype == QType::DS) && signer == qname) {
1850 /* we are already retrieving those keys, sorry */
1851 return Indeterminate;
1852 }
1853 vState state = getDNSKeys(signer, keys, depth);
1854 if (state != Secure) {
1855 return state;
1856 }
1857 }
1858 } else {
1859 LOG(d_prefix<<"Bogus!"<<endl);
1860 return Bogus;
1861 }
1862
1863 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
1864 for (const auto& record : records) {
1865 recordcontents.push_back(record.d_content);
1866 }
1867
1868 LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
1869 if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
1870 LOG(d_prefix<<"Secure!"<<endl);
1871 return Secure;
1872 }
1873
1874 LOG(d_prefix<<"Bogus!"<<endl);
1875 return Bogus;
1876 }
1877
1878 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)
1879 {
1880 tcache_t tcache;
1881
1882 string prefix;
1883 if(doLog()) {
1884 prefix=d_prefix;
1885 prefix.append(depth, ' ');
1886 }
1887
1888 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
1889 const unsigned int labelCount = qname.countLabels();
1890 bool isCNAMEAnswer = false;
1891 for(const auto& rec : lwr.d_records) {
1892 if(!isCNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
1893 isCNAMEAnswer = true;
1894 }
1895
1896 /* if we have a positive answer synthetized from a wildcard,
1897 we need to store the corresponding NSEC/NSEC3 records proving
1898 that the exact name did not exist in the negative cache */
1899 if(needWildcardProof) {
1900 if (nsecTypes.count(rec.d_type)) {
1901 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1902 }
1903 else if (rec.d_type == QType::RRSIG) {
1904 auto rrsig = getRR<RRSIGRecordContent>(rec);
1905 if (rrsig && nsecTypes.count(rrsig->d_type)) {
1906 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1907 }
1908 }
1909 }
1910 if(rec.d_type == QType::RRSIG) {
1911 auto rrsig = getRR<RRSIGRecordContent>(rec);
1912 if (rrsig) {
1913 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
1914 count can be lower than the name's label count if it was
1915 synthetized from the wildcard. Note that the difference might
1916 be > 1. */
1917 if (rec.d_name == qname && rrsig->d_labels < labelCount) {
1918 LOG(prefix<<qname<<": RRSIG indicates the name was synthetized from a wildcard, we need a wildcard proof"<<endl);
1919 needWildcardProof = true;
1920 }
1921
1922 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
1923 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
1924 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);
1925 }
1926 }
1927 }
1928
1929 // reap all answers from this packet that are acceptable
1930 for(auto& rec : lwr.d_records) {
1931 if(rec.d_type == QType::OPT) {
1932 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
1933 continue;
1934 }
1935 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<<" ");
1936 if(rec.d_type == QType::ANY) {
1937 LOG("NO! - we don't accept 'ANY' data"<<endl);
1938 continue;
1939 }
1940
1941 if(rec.d_name.isPartOf(auth)) {
1942 if(rec.d_type == QType::RRSIG) {
1943 LOG("RRSIG - separate"<<endl);
1944 }
1945 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)) {
1946 LOG("NO! Is from delegation-only zone"<<endl);
1947 s_nodelegated++;
1948 return RCode::NXDomain;
1949 }
1950 else {
1951 bool haveLogged = false;
1952 if (!t_sstorage.domainmap->empty()) {
1953 // Check if we are authoritative for a zone in this answer
1954 DNSName tmp_qname(rec.d_name);
1955 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
1956 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
1957 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
1958 if (auth_domain_iter->first != auth) {
1959 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
1960 continue;
1961 } else {
1962 LOG("YES! - This answer was ");
1963 if (!wasForwarded) {
1964 LOG("retrieved from the local auth store.");
1965 } else {
1966 LOG("received from a server we forward to.");
1967 }
1968 haveLogged = true;
1969 LOG(endl);
1970 }
1971 }
1972 }
1973 if (!haveLogged) {
1974 LOG("YES!"<<endl);
1975 }
1976
1977 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
1978
1979 DNSRecord dr(rec);
1980 dr.d_ttl += d_now.tv_sec;
1981 dr.d_place=DNSResourceRecord::ANSWER;
1982 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
1983 }
1984 }
1985 else
1986 LOG("NO!"<<endl);
1987 }
1988
1989 // supplant
1990 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
1991 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)
1992 uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
1993
1994 for(auto& record : i->second.records)
1995 record.d_ttl = lowestTTD; // boom
1996 }
1997
1998 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
1999 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
2000 }
2001
2002 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2003
2004 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
2005 continue;
2006
2007 bool isAA = lwr.d_aabit;
2008 if (isAA && isCNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER || i->first.type != QType::CNAME)) {
2009 /*
2010 rfc2181 states:
2011 Note that the answer section of an authoritative answer normally
2012 contains only authoritative data. However when the name sought is an
2013 alias (see section 10.1.1) only the record describing that alias is
2014 necessarily authoritative. Clients should assume that other records
2015 may have come from the server's cache. Where authoritative answers
2016 are required, the client should query again, using the canonical name
2017 associated with the alias.
2018 */
2019 isAA = false;
2020 }
2021
2022 vState recordState = getValidationStatus(i->first.name, false);
2023 LOG(d_prefix<<": got initial zone status "<<vStates[recordState]<<" for record "<<i->first.name<<endl);
2024
2025 if (d_DNSSECValidationRequested && recordState == Secure) {
2026 vState initialState = recordState;
2027
2028 if (isAA) {
2029 if (i->first.place != DNSResourceRecord::ADDITIONAL) {
2030 /* the additional entries can be insecure,
2031 like glue:
2032 "Glue address RRsets associated with delegations MUST NOT be signed"
2033 */
2034 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) {
2035 LOG(d_prefix<<"Validating DNSKEY for "<<i->first.name<<endl);
2036 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth);
2037 }
2038 else {
2039 LOG(d_prefix<<"Validating non-additional record for "<<i->first.name<<endl);
2040 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2041 /* 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 */
2042 if (qtype == QType::NS && i->second.signatures.empty() && recordState == Bogus && haveExactValidationStatus(i->first.name) && getValidationStatus(i->first.name) == Indeterminate) {
2043 recordState = Indeterminate;
2044 }
2045 }
2046 }
2047 }
2048 else {
2049 /* in a non authoritative answer, we only care about the DS record (or lack of) */
2050 if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
2051 LOG(d_prefix<<"Validating DS record for "<<i->first.name<<endl);
2052 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
2053 }
2054 }
2055
2056 if (initialState == Secure && state != recordState) {
2057 updateValidationState(state, recordState);
2058 }
2059 }
2060 else {
2061 if (d_DNSSECValidationRequested) {
2062 LOG(d_prefix<<"Skipping validation because the current state is "<<vStates[recordState]<<endl);
2063 }
2064 }
2065
2066 /* We don't need to store NSEC3 records in the positive cache because:
2067 - we don't allow direct NSEC3 queries
2068 - denial of existence proofs in wildcard expanded positive responses are stored in authorityRecs
2069 - denial of existence proofs for negative responses are stored in the negative cache
2070 */
2071 if (i->first.type != QType::NSEC3) {
2072 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);
2073 }
2074
2075 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
2076 d_wasVariable=true;
2077 }
2078
2079 return RCode::NoError;
2080 }
2081
2082 void SyncRes::updateDenialValidationState(NegCache::NegCacheEntry& ne, vState& state, const dState denialState, const dState expectedState, bool allowOptOut)
2083 {
2084 if (denialState != expectedState) {
2085 if (denialState == OPTOUT && allowOptOut) {
2086 LOG(d_prefix<<"OPT-out denial found for "<<ne.d_name<<endl);
2087 ne.d_validationState = Secure;
2088 return;
2089 }
2090 else if (denialState == INSECURE) {
2091 LOG(d_prefix<<"Insecure denial found for "<<ne.d_name<<", returning Insecure"<<endl);
2092 ne.d_validationState = Insecure;
2093 }
2094 else {
2095 LOG(d_prefix<<"Invalid denial found for "<<ne.d_name<<", returning Bogus, res="<<denialState<<", expectedState="<<expectedState<<endl);
2096 ne.d_validationState = Bogus;
2097 }
2098 updateValidationState(state, ne.d_validationState);
2099 }
2100 }
2101
2102 dState SyncRes::getDenialValidationState(NegCache::NegCacheEntry& ne, const vState state, const dState expectedState, bool referralToUnsigned)
2103 {
2104 cspmap_t csp = harvestCSPFromNE(ne);
2105 return getDenial(csp, ne.d_name, ne.d_qtype.getCode(), referralToUnsigned, expectedState == NXQTYPE);
2106 }
2107
2108 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)
2109 {
2110 bool done = false;
2111
2112 for(auto& rec : lwr.d_records) {
2113 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
2114 continue;
2115
2116 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2117 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
2118 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
2119
2120 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
2121 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
2122 ret.push_back(rec);
2123
2124 NegCache::NegCacheEntry ne;
2125
2126 uint32_t lowestTTL = rec.d_ttl;
2127 /* if we get an NXDomain answer with a CNAME, the name
2128 does exist but the target does not */
2129 ne.d_name = newtarget.empty() ? qname : newtarget;
2130 ne.d_qtype = QType(0); // this encodes 'whole record'
2131 ne.d_auth = rec.d_name;
2132 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2133 ne.d_ttd = d_now.tv_sec + lowestTTL;
2134
2135 if (state == Secure) {
2136 dState denialState = getDenialValidationState(ne, state, NXDOMAIN, false);
2137 updateDenialValidationState(ne, state, denialState, NXDOMAIN, false);
2138 }
2139 else {
2140 ne.d_validationState = state;
2141 }
2142
2143 /* if we get an NXDomain answer with a CNAME, let's not cache the
2144 target, even the server was authoritative for it,
2145 and do an additional query for the CNAME target.
2146 We have a regression test making sure we do exactly that.
2147 */
2148 if(!wasVariable() && newtarget.empty()) {
2149 t_sstorage.negcache.add(ne);
2150 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
2151 ne.d_name = ne.d_name.getLastLabel();
2152 t_sstorage.negcache.add(ne);
2153 }
2154 }
2155
2156 negindic=true;
2157 }
2158 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
2159 ret.push_back(rec);
2160 if (auto content = getRR<CNAMERecordContent>(rec)) {
2161 newtarget=content->getTarget();
2162 }
2163 }
2164 /* if we have a positive answer synthetized from a wildcard, we need to
2165 return the corresponding NSEC/NSEC3 records from the AUTHORITY section
2166 proving that the exact name did not exist */
2167 else if(needWildcardProof && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::AUTHORITY) {
2168 ret.push_back(rec); // enjoy your DNSSEC
2169 }
2170 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
2171 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
2172 (
2173 rec.d_type==qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType(QType::ANY))
2174 )
2175 )
2176 {
2177 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
2178
2179 done=true;
2180 ret.push_back(rec);
2181
2182 if (state == Secure && needWildcardProof) {
2183 /* We have a positive answer synthetized from a wildcard, we need to check that we have
2184 proof that the exact name doesn't exist so the wildcard can be used,
2185 as described in section 5.3.4 of RFC 4035 and 5.3 of FRC 7129.
2186 */
2187 NegCache::NegCacheEntry ne;
2188
2189 uint32_t lowestTTL = rec.d_ttl;
2190 ne.d_name = qname;
2191 ne.d_qtype = QType(0); // this encodes 'whole record'
2192 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2193
2194 cspmap_t csp = harvestCSPFromNE(ne);
2195 dState res = getDenial(csp, qname, ne.d_qtype.getCode(), false, false, false);
2196 if (res != NXDOMAIN) {
2197 vState st = Bogus;
2198 if (res == INSECURE) {
2199 /* Some part could not be validated, for example a NSEC3 record with a too large number of iterations,
2200 this is not enough to warrant a Bogus, but go Insecure. */
2201 st = Insecure;
2202 LOG(d_prefix<<"Unable to validate denial in wildcard expanded positive response found for "<<qname<<", returning Insecure, res="<<res<<endl);
2203 }
2204 else {
2205 LOG(d_prefix<<"Invalid denial in wildcard expanded positive response found for "<<qname<<", returning Bogus, res="<<res<<endl);
2206 }
2207
2208 updateValidationState(state, st);
2209 /* we already stored the record with a different validation status, let's fix it */
2210 t_RC->updateValidationStatus(d_now.tv_sec, qname, qtype, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, lwr.d_aabit, st);
2211 }
2212 }
2213 }
2214 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER) {
2215 if(rec.d_type != QType::RRSIG || rec.d_name == qname)
2216 ret.push_back(rec); // enjoy your DNSSEC
2217 }
2218 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::NS && qname.isPartOf(rec.d_name)) {
2219 if(moreSpecificThan(rec.d_name,auth)) {
2220 newauth=rec.d_name;
2221 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2222 realreferral=true;
2223 }
2224 else {
2225 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
2226 }
2227 if (auto content = getRR<NSRecordContent>(rec)) {
2228 nsset.insert(content->getNS());
2229 }
2230 }
2231 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
2232 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2233 }
2234 else if(realreferral && rec.d_place==DNSResourceRecord::AUTHORITY && (rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && newauth.isPartOf(auth)) {
2235 /* we might have received a denial of the DS, let's check */
2236 if (state == Secure) {
2237 NegCache::NegCacheEntry ne;
2238 ne.d_auth = auth;
2239 ne.d_name = newauth;
2240 ne.d_qtype = QType::DS;
2241 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2242 uint32_t lowestTTL = rec.d_ttl;
2243 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2244
2245 dState denialState = getDenialValidationState(ne, state, NXQTYPE, true);
2246
2247 if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
2248 ne.d_ttd = lowestTTL + d_now.tv_sec;
2249 ne.d_validationState = Secure;
2250 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
2251
2252 if(!wasVariable()) {
2253 t_sstorage.negcache.add(ne);
2254 }
2255
2256 if (qname == newauth && qtype == QType::DS) {
2257 /* we are actually done! */
2258 negindic=true;
2259 nsset.clear();
2260 }
2261 }
2262 }
2263 }
2264 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2265 lwr.d_rcode==RCode::NoError && qname.isPartOf(rec.d_name)) {
2266 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
2267
2268 if(!newtarget.empty()) {
2269 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
2270 }
2271 else {
2272 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2273 ret.push_back(rec);
2274
2275 NegCache::NegCacheEntry ne;
2276 ne.d_auth = rec.d_name;
2277 uint32_t lowestTTL = rec.d_ttl;
2278 ne.d_name = qname;
2279 ne.d_qtype = qtype;
2280 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2281 ne.d_ttd = d_now.tv_sec + lowestTTL;
2282
2283 if (state == Secure) {
2284 dState denialState = getDenialValidationState(ne, state, NXQTYPE, false);
2285 updateDenialValidationState(ne, state, denialState, NXQTYPE, qtype == QType::DS);
2286 } else {
2287 ne.d_validationState = state;
2288 }
2289
2290 if(!wasVariable()) {
2291 if(qtype.getCode()) { // prevents us from blacking out a whole domain
2292 t_sstorage.negcache.add(ne);
2293 }
2294 }
2295 negindic=true;
2296 }
2297 }
2298 }
2299
2300 return done;
2301 }
2302
2303 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)
2304 {
2305 int resolveret;
2306 s_outqueries++;
2307 d_outqueries++;
2308
2309 if(d_outqueries + d_throttledqueries > s_maxqperq) {
2310 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
2311 }
2312
2313 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
2314 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");
2315 }
2316
2317 if(doTCP) {
2318 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
2319 s_tcpoutqueries++;
2320 d_tcpoutqueries++;
2321 }
2322
2323 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
2324 LOG(prefix<<qname<<": query handled by Lua"<<endl);
2325 }
2326 else {
2327 ednsmask=getEDNSSubnetMask(d_requestor, qname, remoteIP);
2328 if(ednsmask) {
2329 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
2330 s_ecsqueries++;
2331 }
2332 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(),
2333 doTCP, sendRDQuery, &d_now, ednsmask, &lwr); // <- we go out on the wire!
2334 if(ednsmask) {
2335 s_ecsresponses++;
2336 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
2337 }
2338 }
2339
2340 /* preoutquery killed the query by setting dq.rcode to -3 */
2341 if(resolveret==-3) {
2342 throw ImmediateServFailException("Query killed by policy");
2343 }
2344
2345 d_totUsec += lwr.d_usec;
2346 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
2347
2348 if(resolveret != 1) {
2349 /* Error while resolving */
2350 if(resolveret == 0) {
2351 /* Time out */
2352
2353 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
2354 d_timeouts++;
2355 s_outgoingtimeouts++;
2356
2357 if(remoteIP.sin4.sin_family == AF_INET)
2358 s_outgoing4timeouts++;
2359 else
2360 s_outgoing6timeouts++;
2361 }
2362 else if(resolveret == -2) {
2363 /* OS resource limit reached */
2364 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
2365 g_stats.resourceLimits++;
2366 }
2367 else {
2368 /* -1 means server unreachable */
2369 s_unreachables++;
2370 d_unreachables++;
2371 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
2372 }
2373
2374 if(resolveret != -2) { // don't account for resource limits, they are our own fault
2375 t_sstorage.nsSpeeds[nsName].submit(remoteIP, 1000000, &d_now); // 1 sec
2376
2377 // code below makes sure we don't filter COM or the root
2378 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) {
2379 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
2380 // mark server as down
2381 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
2382 }
2383 else if (resolveret == -1) {
2384 // unreachable, 1 minute or 100 queries
2385 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
2386 }
2387 else {
2388 // timeout
2389 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
2390 }
2391 }
2392
2393 return false;
2394 }
2395
2396 /* we got an answer */
2397 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
2398 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
2399 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2400 return false;
2401 }
2402
2403 /* this server sent a valid answer, mark it backup up if it was down */
2404 if(s_serverdownmaxfails > 0) {
2405 t_sstorage.fails.clear(remoteIP);
2406 }
2407
2408 if(lwr.d_tcbit) {
2409 *truncated = true;
2410
2411 if (doTCP) {
2412 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
2413 /* let's treat that as a ServFail answer from this server */
2414 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2415 return false;
2416 }
2417
2418 return true;
2419 }
2420
2421 return true;
2422 }
2423
2424 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)
2425 {
2426 string prefix;
2427 if(doLog()) {
2428 prefix=d_prefix;
2429 prefix.append(depth, ' ');
2430 }
2431
2432 if(s_minimumTTL) {
2433 for(auto& rec : lwr.d_records) {
2434 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
2435 }
2436 }
2437
2438 bool needWildcardProof = false;
2439 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, needWildcardProof);
2440 if (*rcode != RCode::NoError) {
2441 return true;
2442 }
2443
2444 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
2445
2446 set<DNSName> nsset;
2447 bool realreferral=false, negindic=false;
2448 DNSName newauth;
2449 DNSName newtarget;
2450
2451 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof);
2452
2453 if(done){
2454 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
2455 LOG(prefix<<qname<<": validation status is "<<vStates[state]<<endl);
2456 *rcode = RCode::NoError;
2457 return true;
2458 }
2459
2460 if(!newtarget.empty()) {
2461 if(newtarget == qname) {
2462 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
2463 *rcode = RCode::ServFail;
2464 return true;
2465 }
2466
2467 if(depth > 10) {
2468 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
2469 *rcode = RCode::ServFail;
2470 return true;
2471 }
2472
2473 if (qtype == QType::DS) {
2474 LOG(prefix<<qname<<": status=got a CNAME referral, but we are looking for a DS"<<endl);
2475
2476 if(d_doDNSSEC)
2477 addNXNSECS(ret, lwr.d_records);
2478
2479 *rcode = RCode::NoError;
2480 return true;
2481 }
2482 else {
2483 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
2484
2485 set<GetBestNSAnswer> beenthere2;
2486 vState cnameState = Indeterminate;
2487 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState);
2488 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
2489 updateValidationState(state, cnameState);
2490 return true;
2491 }
2492 }
2493
2494 if(lwr.d_rcode == RCode::NXDomain) {
2495 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
2496
2497 if(d_doDNSSEC)
2498 addNXNSECS(ret, lwr.d_records);
2499
2500 *rcode = RCode::NXDomain;
2501 return true;
2502 }
2503
2504 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
2505 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
2506
2507 if(state == Secure && lwr.d_aabit && !negindic) {
2508 updateValidationState(state, Bogus);
2509 }
2510
2511 if(d_doDNSSEC)
2512 addNXNSECS(ret, lwr.d_records);
2513
2514 *rcode = RCode::NoError;
2515 return true;
2516 }
2517
2518 if(realreferral) {
2519 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
2520
2521 nameservers.clear();
2522 for (auto const &nameserver : nsset) {
2523 if (d_wantsRPZ) {
2524 d_appliedPolicy = dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
2525 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2526 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
2527 *rcode = -2;
2528 return true;
2529 }
2530 }
2531 nameservers.insert({nameserver, {{}, false}});
2532 }
2533 LOG("looping to them"<<endl);
2534 *gotNewServers = true;
2535 auth=newauth;
2536
2537 return false;
2538 }
2539
2540 return false;
2541 }
2542
2543 /** returns:
2544 * -1 in case of no results
2545 * -2 when a FilterEngine Policy was hit
2546 * rcode otherwise
2547 */
2548 int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
2549 vector<DNSRecord>&ret,
2550 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state)
2551 {
2552 auto luaconfsLocal = g_luaconfs.getLocal();
2553 string prefix;
2554 if(doLog()) {
2555 prefix=d_prefix;
2556 prefix.append(depth, ' ');
2557 }
2558
2559 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
2560
2561 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
2562 return -2;
2563 }
2564
2565 LOG(endl);
2566
2567 for(;;) { // we may get more specific nameservers
2568 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
2569
2570 for(auto tns=rnameservers.cbegin();;++tns) {
2571 if(tns==rnameservers.cend()) {
2572 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
2573 if(!auth.isRoot() && flawedNSSet) {
2574 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
2575
2576 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
2577 g_stats.nsSetInvalidations++;
2578 }
2579 return -1;
2580 }
2581
2582 bool cacheOnly = false;
2583 // this line needs to identify the 'self-resolving' behaviour
2584 if(qname == *tns && (qtype.getCode() == QType::A || qtype.getCode() == QType::AAAA)) {
2585 /* we might have a glue entry in cache so let's try this NS
2586 but only if we have enough in the cache to know how to reach it */
2587 LOG(prefix<<qname<<": Using NS to resolve itself, but only using what we have in cache ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
2588 cacheOnly = true;
2589 }
2590
2591 typedef vector<ComboAddress> remoteIPs_t;
2592 remoteIPs_t remoteIPs;
2593 remoteIPs_t::const_iterator remoteIP;
2594 bool pierceDontQuery=false;
2595 bool sendRDQuery=false;
2596 boost::optional<Netmask> ednsmask;
2597 LWResult lwr;
2598 const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty());
2599 int rcode = RCode::NoError;
2600 bool gotNewServers = false;
2601
2602 if(tns->empty() && !wasForwarded) {
2603 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
2604 state = Insecure;
2605 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
2606 lwr.d_tcbit=false;
2607 lwr.d_aabit=true;
2608
2609 /* we have received an answer, are we done ? */
2610 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
2611 if (done) {
2612 return rcode;
2613 }
2614 if (gotNewServers) {
2615 break;
2616 }
2617 }
2618 else {
2619 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
2620 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly);
2621
2622 if(remoteIPs.empty()) {
2623 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
2624 flawedNSSet=true;
2625 continue;
2626 }
2627 else {
2628 bool hitPolicy{false};
2629 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
2630 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2631 if(remoteIP != remoteIPs.cbegin()) {
2632 LOG(", ");
2633 }
2634 LOG(remoteIP->toString());
2635 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
2636 hitPolicy = true;
2637 }
2638 }
2639 LOG(endl);
2640 if (hitPolicy) //implies d_wantsRPZ
2641 return -2;
2642 }
2643
2644 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2645 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
2646
2647 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
2648 continue;
2649 }
2650
2651 bool truncated = false;
2652 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2653 *tns, *remoteIP, false, &truncated);
2654 if (gotAnswer && truncated ) {
2655 /* retry, over TCP this time */
2656 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2657 *tns, *remoteIP, true, &truncated);
2658 }
2659
2660 if (!gotAnswer) {
2661 continue;
2662 }
2663
2664 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);
2665
2666 /* // for you IPv6 fanatics :-)
2667 if(remoteIP->sin4.sin_family==AF_INET6)
2668 lwr.d_usec/=3;
2669 */
2670 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
2671
2672 t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
2673
2674 /* we have received an answer, are we done ? */
2675 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
2676 if (done) {
2677 return rcode;
2678 }
2679 if (gotNewServers) {
2680 break;
2681 }
2682 /* was lame */
2683 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
2684 }
2685
2686 if (gotNewServers) {
2687 break;
2688 }
2689
2690 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
2691 continue;
2692
2693 }
2694 }
2695 }
2696 return -1;
2697 }
2698
2699 void SyncRes::setIncomingECS(boost::optional<const EDNSSubnetOpts&> incomingECS)
2700 {
2701 d_incomingECS = incomingECS;
2702 if (incomingECS) {
2703 if (d_incomingECS->source.getBits() == 0) {
2704 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0.
2705 But using an empty ECS in that case would mean inserting
2706 a non ECS-specific entry into the cache, preventing any further
2707 ECS-specific query to be sent.
2708 So instead we use the trick described in section 7.1.2:
2709 "The subsequent Recursive Resolver query to the Authoritative Nameserver
2710 will then either not include an ECS option or MAY optionally include
2711 its own address information, which is what the Authoritative
2712 Nameserver will almost certainly use to generate any Tailored
2713 Response in lieu of an option. This allows the answer to be handled
2714 by the same caching mechanism as other queries, with an explicit
2715 indicator of the applicable scope. Subsequent Stub Resolver queries
2716 for /0 can then be answered from this cached response.
2717 */
2718 d_incomingECS = s_ecsScopeZero;
2719 d_incomingECSNetwork = s_ecsScopeZero.source.getMaskedNetwork();
2720 }
2721 else {
2722 uint8_t bits = std::min(incomingECS->source.getBits(), (incomingECS->source.isIpv4() ? s_ecsipv4limit : s_ecsipv6limit));
2723 d_incomingECS->source = Netmask(incomingECS->source.getNetwork(), bits);
2724 d_incomingECSNetwork = d_incomingECS->source.getMaskedNetwork();
2725 }
2726 }
2727 else {
2728 d_incomingECSNetwork = ComboAddress();
2729 }
2730 }
2731
2732 boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem)
2733 {
2734 boost::optional<Netmask> result;
2735 ComboAddress trunc;
2736 uint8_t bits;
2737 if(d_incomingECSFound) {
2738 trunc = d_incomingECSNetwork;
2739 bits = d_incomingECS->source.getBits();
2740 }
2741 else if(!local.isIPv4() || local.sin4.sin_addr.s_addr) { // detect unset 'requestor'
2742 trunc = local;
2743 bits = local.isIPv4() ? 32 : 128;
2744 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
2745 }
2746 else {
2747 /* nothing usable */
2748 return result;
2749 }
2750
2751 if(s_ednsdomains.check(dn) || s_ednssubnets.match(rem)) {
2752 trunc.truncate(bits);
2753 return boost::optional<Netmask>(Netmask(trunc, bits));
2754 }
2755
2756 return result;
2757 }
2758
2759 void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
2760 {
2761 vector<string> parts;
2762 stringtok(parts, wlist, ",; ");
2763 for(const auto& a : parts) {
2764 try {
2765 s_ednssubnets.addMask(Netmask(a));
2766 }
2767 catch(...) {
2768 s_ednsdomains.add(DNSName(a));
2769 }
2770 }
2771 }
2772
2773 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
2774 int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
2775 {
2776 struct timeval now;
2777 gettimeofday(&now, 0);
2778
2779 SyncRes sr(now);
2780 int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
2781
2782 return res;
2783 }
2784
2785 int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
2786 SyncRes sr(now);
2787 sr.setDoEDNS0(true);
2788 sr.setUpdatingRootNS();
2789 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
2790 sr.setDNSSECValidationRequested(g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate);
2791 sr.setAsyncCallback(asyncCallback);
2792
2793 vector<DNSRecord> ret;
2794 int res=-1;
2795 try {
2796 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
2797 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
2798 auto state = sr.getValidationState();
2799 if (state == Bogus)
2800 throw PDNSException("Got Bogus validation result for .|NS");
2801 }
2802 return res;
2803 }
2804 catch(const PDNSException& e) {
2805 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2806 }
2807 catch(const ImmediateServFailException& e) {
2808 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2809 }
2810 catch(const std::exception& e) {
2811 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
2812 }
2813 catch(...) {
2814 L<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
2815 }
2816
2817 if(!res) {
2818 L<<Logger::Notice<<"Refreshed . records"<<endl;
2819 }
2820 else
2821 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
2822
2823 return res;
2824 }