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