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