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