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