]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/syncres.cc
rec: Refuse queries for rfc6895 section 3.1 meta types
[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{
3f8a73d6
RG
122 /* rfc6895 section 3.1 + RRSIG and NSEC3 */
123 static const std::set<uint16_t> metaTypes = { QType::AXFR, QType::IXFR, QType::RRSIG, QType::NSEC3, QType::OPT, QType::TSIG, QType::TKEY, QType::MAILA, QType::MAILB };
4d2be65d 124 vState state = Indeterminate;
c836dc19 125 s_queries++;
3762e821 126 d_wasVariable=false;
9fc36e90 127 d_wasOutOfBand=false;
710af846 128
4d2be65d 129 if (doSpecialNamesResolve(qname, qtype, qclass, ret)) {
d04ac108 130 d_queryValidationState = Insecure; // this could fool our stats into thinking a validation took place
131 return 0; // so do check before updating counters (we do now)
4d2be65d 132 }
db50a7f4 133
3f8a73d6 134 if (metaTypes.count(qtype.getCode())) {
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 {
0bd2e252 497 ret=asyncresolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, d_outgoingProtobufServer, 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 ) {
269ac73d 507 if(res->d_validpacket && 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
e1636f82 944 if (!wasAuthZone && shouldValidate() && wasAuth && 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 }
28364e4b
RG
1140 else if (t_sstorage.negcache.get(qname, qtype, d_now, &ne) &&
1141 !(wasForwardedOrAuthZone && ne->d_auth != authname)) { // Only the authname nameserver can neg cache entries
b0c164a2
RG
1142
1143 /* If we are looking for a DS, discard NXD if auth == qname
1144 and ask for a specific denial instead */
28364e4b
RG
1145 if (qtype != QType::DS || ne->d_qtype.getCode() || ne->d_auth != qname ||
1146 t_sstorage.negcache.get(qname, qtype, d_now, &ne, true))
b0c164a2
RG
1147 {
1148 res = 0;
28364e4b 1149 sttl = ne->d_ttd - d_now.tv_sec;
b0c164a2 1150 giveNegative = true;
28364e4b
RG
1151 cachedState = ne->d_validationState;
1152 if(ne->d_qtype.getCode()) {
1153 LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne->d_auth<<"' for another "<<sttl<<" seconds"<<endl);
b0c164a2
RG
1154 res = RCode::NoError;
1155 }
1156 else {
28364e4b 1157 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne->d_auth<<"' for another "<<sttl<<" seconds"<<endl);
b0c164a2
RG
1158 res = RCode::NXDomain;
1159 }
39ce10b2 1160 }
39ce10b2
PL
1161 }
1162
1163 if (giveNegative) {
142ab370
RG
1164
1165 state = cachedState;
1166
e1636f82 1167 if (!wasAuthZone && shouldValidate() && state == Indeterminate) {
142ab370
RG
1168 LOG(prefix<<qname<<": got Indeterminate state for records retrieved from the negative cache, validating.."<<endl);
1169 computeNegCacheValidationStatus(ne, qname, qtype, res, state, depth);
1170 }
1171
39ce10b2 1172 // Transplant SOA to the returned packet
28364e4b 1173 addTTLModifiedRecords(ne->authoritySOA.records, sttl, ret);
4d00b38b 1174 if(d_doDNSSEC) {
28364e4b
RG
1175 addTTLModifiedRecords(ne->authoritySOA.signatures, sttl, ret);
1176 addTTLModifiedRecords(ne->DNSSECRecords.records, sttl, ret);
1177 addTTLModifiedRecords(ne->DNSSECRecords.signatures, sttl, ret);
4d00b38b 1178 }
4d2be65d 1179
142ab370 1180 LOG(prefix<<qname<<": updating validation state with negative cache content for "<<qname<<" to "<<vStates[state]<<endl);
39ce10b2 1181 return true;
fd8bc993 1182 }
39ce10b2 1183
e325f20c 1184 vector<DNSRecord> cset;
75b49099 1185 bool found=false, expired=false;
57769f13 1186 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
2b984251 1187 vector<std::shared_ptr<DNSRecord>> authorityRecs;
57769f13 1188 uint32_t ttl=0;
428f41b7 1189 bool wasCachedAuth;
ad797d94 1190 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 1191
2189085d 1192 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
428f41b7 1193
e1636f82 1194 if (!wasAuthZone && shouldValidate() && wasCachedAuth && cachedState == Indeterminate && d_requireAuthData) {
428f41b7
RG
1195
1196 /* This means we couldn't figure out the state when this entry was cached,
1197 most likely because we hadn't computed the zone cuts yet. */
aa30ad7e 1198 /* make sure they are computed before validating */
f4de85a3
RG
1199 DNSName subdomain(sqname);
1200 /* if we are retrieving a DS, we only care about the state of the parent zone */
1201 if(qtype == QType::DS)
1202 subdomain.chopOff();
1203
1204 computeZoneCuts(subdomain, g_rootdnsname, depth);
aa30ad7e 1205
142ab370 1206 vState recordState = getValidationStatus(qname, false);
787737ae
RG
1207 if (recordState == Secure) {
1208 LOG(prefix<<sqname<<": got Indeterminate state from the cache, validating.."<<endl);
1209 cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures);
f4de85a3
RG
1210 }
1211 else {
1212 cachedState = recordState;
1213 }
787737ae 1214
f4de85a3
RG
1215 if (cachedState != Indeterminate) {
1216 LOG(prefix<<qname<<": got Indeterminate state from the cache, validation result is "<<vStates[cachedState]<<endl);
2fe3354d 1217 t_RC->updateValidationStatus(d_now.tv_sec, sqname, sqt, d_cacheRemote, d_requireAuthData, cachedState);
787737ae 1218 }
428f41b7
RG
1219 }
1220
e325f20c 1221 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
c5310862 1222
e325f20c 1223 LOG(j->d_content->getZoneRepresentation());
c5310862
RG
1224
1225 if (j->d_class != QClass::IN) {
1226 continue;
1227 }
1228
e325f20c 1229 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
1230 DNSRecord dr=*j;
1231 ttl = (dr.d_ttl-=d_now.tv_sec);
e325f20c 1232 ret.push_back(dr);
1233 LOG("[ttl="<<dr.d_ttl<<"] ");
4957a608 1234 found=true;
ac539791 1235 }
75b49099 1236 else {
77499b05 1237 LOG("[expired] ");
4957a608 1238 expired=true;
75b49099 1239 }
afbe2787 1240 }
57769f13 1241
f128d20d
RG
1242 ret.reserve(ret.size() + signatures.size() + authorityRecs.size());
1243
57769f13 1244 for(const auto& signature : signatures) {
e325f20c 1245 DNSRecord dr;
1246 dr.d_type=QType::RRSIG;
1247 dr.d_name=sqname;
1248 dr.d_ttl=ttl;
1249 dr.d_content=signature;
39ce10b2 1250 dr.d_place = DNSResourceRecord::ANSWER;
4d2be65d 1251 dr.d_class=QClass::IN;
e325f20c 1252 ret.push_back(dr);
57769f13 1253 }
2b984251
RG
1254
1255 for(const auto& rec : authorityRecs) {
1256 DNSRecord dr(*rec);
1257 dr.d_ttl=ttl;
1258 ret.push_back(dr);
1259 }
1260
77499b05 1261 LOG(endl);
f4df5e89 1262 if(found && !expired) {
4d2be65d 1263 if (!giveNegative)
4957a608 1264 res=0;
bcb05770 1265 LOG(prefix<<qname<<": updating validation state with cache content for "<<qname<<" to "<<vStates[cachedState]<<endl);
4d2be65d 1266 state = cachedState;
75b49099 1267 return true;
f4df5e89 1268 }
75b49099 1269 else
2189085d 1270 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
afbe2787 1271 }
f4df5e89 1272
75b49099
BH
1273 return false;
1274}
afbe2787 1275
69cbdef9 1276bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
75b49099 1277{
6a1010f7 1278 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
afbe2787
BH
1279}
1280
d8d0bb8f 1281struct speedOrder
eefd15f9 1282{
3ddb9247
PD
1283 speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
1284 bool operator()(const DNSName &a, const DNSName &b) const
c3d9d009
BH
1285 {
1286 return d_speeds[a] < d_speeds[b];
c3d9d009 1287 }
3ddb9247 1288 map<DNSName, double>& d_speeds;
c3d9d009
BH
1289};
1290
fa1b87ff 1291inline vector<DNSName> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
afbe2787 1292{
e8b23f3b 1293 vector<DNSName> rnameservers;
5ea6f7de 1294 rnameservers.reserve(tnameservers.size());
a2d65f83 1295 for(const auto& tns: tnameservers) {
88490c03 1296 rnameservers.push_back(tns.first);
a2d65f83 1297 if(tns.first.empty()) // this was an authoritative OOB zone, don't pollute the nsSpeeds with that
1298 return rnameservers;
21f0f88b 1299 }
e8b23f3b 1300 map<DNSName, double> speeds;
461df9d2 1301
e8b23f3b 1302 for(const auto& val: rnameservers) {
79b8cdcc 1303 double speed;
a712cb56 1304 speed=t_sstorage.nsSpeeds[val].get(&d_now);
21f0f88b 1305 speeds[val]=speed;
eefd15f9 1306 }
51e2144e 1307 random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
996c89cc
BH
1308 speedOrder so(speeds);
1309 stable_sort(rnameservers.begin(),rnameservers.end(), so);
710af846 1310
77499b05
BH
1311 if(doLog()) {
1312 LOG(prefix<<"Nameservers: ");
e325f20c 1313 for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
3ddb9247 1314 if(i!=rnameservers.begin()) {
77499b05
BH
1315 LOG(", ");
1316 if(!((i-rnameservers.begin())%3)) {
1317 LOG(endl<<prefix<<" ");
1318 }
d8d0bb8f 1319 }
317f7521 1320 LOG(i->toLogString()<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
d8d0bb8f 1321 }
77499b05 1322 LOG(endl);
d8d0bb8f 1323 }
728485ca 1324 return rnameservers;
afbe2787
BH
1325}
1326
cc11d7f4 1327inline vector<ComboAddress> SyncRes::shuffleForwardSpeed(const vector<ComboAddress> &rnameservers, const string &prefix, const bool wasRd)
589884b8 1328{
cc11d7f4 1329 vector<ComboAddress> nameservers = rnameservers;
6ed0c28a 1330 map<ComboAddress, double> speeds;
589884b8 1331
cc11d7f4 1332 for(const auto& val: nameservers) {
589884b8 1333 double speed;
6ed0c28a 1334 DNSName nsName = DNSName(val.toStringWithPort());
1335 speed=t_sstorage.nsSpeeds[nsName].get(&d_now);
589884b8 1336 speeds[val]=speed;
1337 }
cc11d7f4 1338 random_shuffle(nameservers.begin(),nameservers.end(), dns_random);
6ed0c28a 1339 speedOrderCA so(speeds);
cc11d7f4 1340 stable_sort(nameservers.begin(),nameservers.end(), so);
589884b8 1341
589884b8 1342 if(doLog()) {
1343 LOG(prefix<<"Nameservers: ");
cc11d7f4 1344 for(vector<ComboAddress>::const_iterator i=nameservers.cbegin();i!=nameservers.cend();++i) {
1345 if(i!=nameservers.cbegin()) {
589884b8 1346 LOG(", ");
cc11d7f4 1347 if(!((i-nameservers.cbegin())%3)) {
589884b8 1348 LOG(endl<<prefix<<" ");
1349 }
1350 }
6ed0c28a 1351 LOG((wasRd ? string("+") : string("-")) << i->toStringWithPort() <<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
589884b8 1352 }
1353 LOG(endl);
1354 }
cc11d7f4 1355 return nameservers;
589884b8 1356}
1357
dbbef467
RG
1358static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<RRSIGRecordContent>& rrsig)
1359{
1360 uint32_t res = 0;
1361 if (now < rrsig->d_sigexpire) {
1362 res = static_cast<uint32_t>(rrsig->d_sigexpire) - now;
1363 }
1364 return res;
1365}
1366
2b984251
RG
1367static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
1368
39ce10b2
PL
1369/* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1370 *
1371 * \param records The records to parse for the authority SOA and NSEC(3) records
1372 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1373 */
dbbef467 1374static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne, const time_t now, uint32_t* lowestTTL) {
620db2c8 1375 for(const auto& rec : records) {
39ce10b2
PL
1376 if(rec.d_place != DNSResourceRecord::AUTHORITY)
1377 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1378 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1379 // records MUST be in the same section as the records they cover.
1380 // Hence, we ignore all records outside of the AUTHORITY section.
1381 continue;
1382
620db2c8 1383 if(rec.d_type == QType::RRSIG) {
39ce10b2
PL
1384 auto rrsig = getRR<RRSIGRecordContent>(rec);
1385 if(rrsig) {
1386 if(rrsig->d_type == QType::SOA) {
1387 ne.authoritySOA.signatures.push_back(rec);
dbbef467
RG
1388 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1389 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1390 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1391 }
39ce10b2
PL
1392 }
1393 if(nsecTypes.count(rrsig->d_type)) {
1394 ne.DNSSECRecords.signatures.push_back(rec);
dbbef467
RG
1395 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1396 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1397 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1398 }
39ce10b2
PL
1399 }
1400 }
1401 continue;
1402 }
1403 if(rec.d_type == QType::SOA) {
1404 ne.authoritySOA.records.push_back(rec);
dbbef467
RG
1405 if (lowestTTL) {
1406 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1407 }
39ce10b2
PL
1408 continue;
1409 }
1410 if(nsecTypes.count(rec.d_type)) {
1411 ne.DNSSECRecords.records.push_back(rec);
dbbef467
RG
1412 if (lowestTTL) {
1413 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1414 }
39ce10b2 1415 continue;
620db2c8 1416 }
620db2c8 1417 }
620db2c8 1418}
1419
4d2be65d
RG
1420static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
1421{
1422 cspmap_t cspmap;
1423 for(const auto& rec : ne.DNSSECRecords.signatures) {
1424 if(rec.d_type == QType::RRSIG) {
1425 auto rrc = getRR<RRSIGRecordContent>(rec);
1426 if (rrc) {
1427 cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
1428 }
1429 }
1430 }
1431 for(const auto& rec : ne.DNSSECRecords.records) {
1432 cspmap[{rec.d_name, rec.d_type}].records.push_back(rec.d_content);
1433 }
1434 return cspmap;
1435}
1436
39ce10b2
PL
1437// TODO remove after processRecords is fixed!
1438// Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
620db2c8 1439static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1440{
39ce10b2 1441 NegCache::NegCacheEntry ne;
dbbef467 1442 harvestNXRecords(records, ne, 0, nullptr);
39ce10b2
PL
1443 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
1444 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
1445 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
620db2c8 1446}
1447
69cbdef9 1448bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
26ca3513
RG
1449{
1450 if(d_wantsRPZ) {
1451 for (auto const &ns : nameservers) {
69cbdef9 1452 d_appliedPolicy = dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
26ca3513
RG
1453 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1454 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1455 return true;
1456 }
1457
1458 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1459 for (auto const &address : ns.second.first) {
69cbdef9 1460 d_appliedPolicy = dfe.getProcessingPolicy(address, d_discardedPolicies);
26ca3513
RG
1461 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1462 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1463 return true;
1464 }
1465 }
1466 }
1467 }
1468 return false;
1469}
1470
69cbdef9 1471bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
26ca3513
RG
1472{
1473 if (d_wantsRPZ) {
69cbdef9 1474 d_appliedPolicy = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies);
26ca3513
RG
1475 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
1476 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
1477 return true;
1478 }
1479 }
1480 return false;
1481}
1482
b4c8789a 1483vector<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
1484{
1485 vector<ComboAddress> result;
1486
1487 if(!tns->empty()) {
1488 LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
b4c8789a 1489 result = getAddrs(*tns, depth+2, beenthere, cacheOnly);
26ca3513
RG
1490 pierceDontQuery=false;
1491 }
1492 else {
1493 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
1494
589884b8 1495 if(nameservers[*tns].first.size() > 1) {
26ca3513
RG
1496 LOG("s");
1497 }
1498 LOG(endl);
1499
1500 sendRDQuery = nameservers[*tns].second;
589884b8 1501 result = shuffleForwardSpeed(nameservers[*tns].first, doLog() ? (prefix+qname.toString()+": ") : string(), sendRDQuery);
26ca3513
RG
1502 pierceDontQuery=true;
1503 }
1504 return result;
1505}
1506
1507bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1508{
a712cb56 1509 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
26ca3513
RG
1510 LOG(prefix<<qname<<": server throttled "<<endl);
1511 s_throttledqueries++; d_throttledqueries++;
1512 return true;
1513 }
a712cb56 1514 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
6dfff36f 1515 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
26ca3513
RG
1516 s_throttledqueries++; d_throttledqueries++;
1517 return true;
1518 }
9065eb05 1519 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
26ca3513
RG
1520 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
1521 s_dontqueries++;
1522 return true;
1523 }
1524 return false;
1525}
1526
4d2be65d
RG
1527bool SyncRes::validationEnabled() const
1528{
8455425c 1529 return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
4d2be65d
RG
1530}
1531
1532uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const
26ca3513 1533{
4d2be65d
RG
1534 uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
1535 for(const auto& record : records)
1536 lowestTTD = min(lowestTTD, record.d_ttl);
1537
0c43f455
RG
1538 /* even if it was not requested for that request (Process, and neither AD nor DO set),
1539 it might be requested at a later time so we need to be careful with the TTL. */
4d2be65d 1540 if (validationEnabled() && !signatures.empty()) {
3cef03e9 1541 /* if we are validating, we don't want to cache records after their signatures expire. */
4d2be65d
RG
1542 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
1543 lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
1544
1545 for(const auto& sig : signatures) {
dbbef467
RG
1546 if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
1547 // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
4d2be65d
RG
1548 lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
1549 }
1550 }
1551 }
1552
1553 return lowestTTD;
1554}
1555
1556void SyncRes::updateValidationState(vState& state, const vState stateUpdate)
1557{
f715542c 1558 LOG(d_prefix<<"validation state was "<<std::string(vStates[state])<<", state update is "<<std::string(vStates[stateUpdate]));
4d2be65d 1559
895449a5
RG
1560 if (stateUpdate == TA) {
1561 state = Secure;
4d2be65d
RG
1562 }
1563 else if (stateUpdate == NTA) {
1564 state = Insecure;
1565 }
895449a5
RG
1566 else if (stateUpdate == Bogus) {
1567 state = Bogus;
1568 }
1569 else if (state == Indeterminate) {
1570 state = stateUpdate;
1571 }
4d2be65d
RG
1572 else if (stateUpdate == Insecure) {
1573 if (state != Bogus) {
1574 state = Insecure;
1575 }
1576 }
f715542c 1577 LOG(", validation state is now "<<std::string(vStates[state])<<endl);
4d2be65d
RG
1578}
1579
1580vState SyncRes::getTA(const DNSName& zone, dsmap_t& ds)
1581{
1582 auto luaLocal = g_luaconfs.getLocal();
1583
1584 if (luaLocal->dsAnchors.empty()) {
e77f01d1 1585 LOG(d_prefix<<": No trust anchors configured, everything is Insecure"<<endl);
4d2be65d
RG
1586 /* We have no TA, everything is insecure */
1587 return Insecure;
1588 }
1589
1590 std::string reason;
1591 if (haveNegativeTrustAnchor(luaLocal->negAnchors, zone, reason)) {
e77f01d1 1592 LOG(d_prefix<<": got NTA for '"<<zone<<"'"<<endl);
4d2be65d
RG
1593 return NTA;
1594 }
1595
1596 if (getTrustAnchor(luaLocal->dsAnchors, zone, ds)) {
e77f01d1 1597 LOG(d_prefix<<": got TA for '"<<zone<<"'"<<endl);
895449a5 1598 return TA;
4d2be65d 1599 }
e77f01d1 1600 else {
1601 LOG(d_prefix<<": no TA found for '"<<zone<<"' among "<< luaLocal->dsAnchors.size()<<endl);
1602 }
4d2be65d
RG
1603
1604 if (zone.isRoot()) {
1605 /* No TA for the root */
1606 return Insecure;
1607 }
1608
1609 return Indeterminate;
1610}
1611
8455425c
RG
1612static size_t countSupportedDS(const dsmap_t& dsmap)
1613{
1614 size_t count = 0;
1615
1616 for (const auto& ds : dsmap) {
1617 if (isSupportedDS(ds)) {
1618 count++;
1619 }
1620 }
1621
1622 return count;
1623}
1624
5374b03b 1625vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsigned int depth, bool bogusOnNXD, bool* foundCut)
4d2be65d
RG
1626{
1627 vState result = getTA(zone, ds);
1628
1629 if (result != Indeterminate || taOnly) {
5374b03b
RG
1630 if (foundCut) {
1631 *foundCut = (result != Indeterminate);
1632 }
1633
18159e92
RG
1634 if (result == TA) {
1635 if (countSupportedDS(ds) == 0) {
1636 ds.clear();
1637 result = Insecure;
1638 }
1639 else {
1640 result = Secure;
1641 }
1642 }
1643 else if (result == NTA) {
8455425c
RG
1644 result = Insecure;
1645 }
1646
4d2be65d
RG
1647 return result;
1648 }
1649
1650 bool oldSkipCNAME = d_skipCNAMECheck;
4d2be65d 1651 d_skipCNAMECheck = true;
4d2be65d
RG
1652
1653 std::set<GetBestNSAnswer> beenthere;
1654 std::vector<DNSRecord> dsrecords;
1655
1656 vState state = Indeterminate;
51b6b728 1657 int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state);
4d2be65d 1658 d_skipCNAMECheck = oldSkipCNAME;
4d2be65d 1659
3ca6d908 1660 if (rcode == RCode::NoError || (rcode == RCode::NXDomain && !bogusOnNXD)) {
5374b03b 1661
1e332f68
PL
1662 uint8_t bestDigestType = 0;
1663
4d2be65d 1664 if (state == Secure) {
1c39e884 1665 bool gotCNAME = false;
4d2be65d
RG
1666 for (const auto& record : dsrecords) {
1667 if (record.d_type == QType::DS) {
1668 const auto dscontent = getRR<DSRecordContent>(record);
8455425c 1669 if (dscontent && isSupportedDS(*dscontent)) {
1e332f68
PL
1670 // Make GOST a lower prio than SHA256
1671 if (dscontent->d_digesttype == DNSSECKeeper::GOST && bestDigestType == DNSSECKeeper::SHA256) {
1672 continue;
1673 }
1674 if (dscontent->d_digesttype > bestDigestType || (bestDigestType == DNSSECKeeper::GOST && dscontent->d_digesttype == DNSSECKeeper::SHA256)) {
1675 bestDigestType = dscontent->d_digesttype;
1676 }
4d2be65d
RG
1677 ds.insert(*dscontent);
1678 }
1679 }
1c39e884
RG
1680 else if (record.d_type == QType::CNAME && record.d_name == zone) {
1681 gotCNAME = true;
1682 }
4d2be65d 1683 }
4d2be65d 1684
1e332f68
PL
1685 /* RFC 4509 section 3: "Validator implementations SHOULD ignore DS RRs containing SHA-1
1686 * digests if DS RRs with SHA-256 digests are present in the DS RRset."
1687 * As SHA348 is specified as well, the spirit of the this line is "use the best algorithm".
1688 */
a211ccb5
RG
1689 for (auto dsrec = ds.begin(); dsrec != ds.end(); ) {
1690 if (dsrec->d_digesttype != bestDigestType) {
1691 dsrec = ds.erase(dsrec);
1692 }
1693 else {
1694 ++dsrec;
1e332f68
PL
1695 }
1696 }
1697
5374b03b
RG
1698 if (rcode == RCode::NoError && ds.empty()) {
1699 if (foundCut) {
1c39e884 1700 if (gotCNAME || denialProvesNoDelegation(zone, dsrecords)) {
5374b03b
RG
1701 /* we are still inside the same Secure zone */
1702
1703 *foundCut = false;
1704 return Secure;
1705 }
1706
1707 *foundCut = true;
1708 }
1709
b7f378d1 1710 return Insecure;
5374b03b
RG
1711 } else if (foundCut && rcode == RCode::NoError && !ds.empty()) {
1712 *foundCut = true;
b7f378d1 1713 }
4d2be65d 1714 }
b7f378d1 1715
4d2be65d
RG
1716 return state;
1717 }
1718
bcb05770 1719 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
4d2be65d
RG
1720 return Bogus;
1721}
1722
0735b60f
RG
1723bool SyncRes::haveExactValidationStatus(const DNSName& domain)
1724{
e1636f82 1725 if (!shouldValidate()) {
0735b60f
RG
1726 return false;
1727 }
1728 const auto& it = d_cutStates.find(domain);
1729 if (it != d_cutStates.cend()) {
1730 return true;
1731 }
1732 return false;
1733}
1734
5374b03b 1735vState SyncRes::getValidationStatus(const DNSName& subdomain, bool allowIndeterminate)
70b3fe7a
RG
1736{
1737 vState result = Indeterminate;
1738
e1636f82 1739 if (!shouldValidate()) {
70b3fe7a
RG
1740 return result;
1741 }
1742 DNSName name(subdomain);
1743 do {
51b6b728
RG
1744 const auto& it = d_cutStates.find(name);
1745 if (it != d_cutStates.cend()) {
5374b03b
RG
1746 if (allowIndeterminate || it->second != Indeterminate) {
1747 LOG(d_prefix<<": got status "<<vStates[it->second]<<" for name "<<subdomain<<" (from "<<name<<")"<<endl);
1748 return it->second;
1749 }
70b3fe7a
RG
1750 }
1751 }
1752 while (name.chopOff());
1753
1754 return result;
1755}
1756
c405e222
RG
1757bool SyncRes::lookForCut(const DNSName& qname, unsigned int depth, const vState existingState, vState& newState)
1758{
1759 bool foundCut = false;
5374b03b
RG
1760 dsmap_t ds;
1761 vState dsState = getDSRecords(qname, ds, newState == Bogus || existingState == Insecure || existingState == Bogus, depth, false, &foundCut);
c405e222 1762
5374b03b
RG
1763 if (dsState != Indeterminate) {
1764 newState = dsState;
1765 }
c405e222 1766
c405e222
RG
1767 return foundCut;
1768}
1769
51b6b728 1770void SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth)
4d2be65d 1771{
428f41b7 1772 if(!begin.isPartOf(end)) {
86f1af1c
KM
1773 LOG(d_prefix<<" "<<begin.toLogString()<<" is not part of "<<end.toLogString()<<endl);
1774 throw PDNSException(begin.toLogString() + " is not part of " + end.toLogString());
428f41b7
RG
1775 }
1776
51b6b728 1777 if (d_cutStates.count(begin) != 0) {
ad75fdbd 1778 return;
4d2be65d
RG
1779 }
1780
1781 dsmap_t ds;
51b6b728 1782 vState cutState = getDSRecords(end, ds, false, depth);
bcb05770 1783 LOG(d_prefix<<": setting cut state for "<<end<<" to "<<vStates[cutState]<<endl);
51b6b728 1784 d_cutStates[end] = cutState;
70b3fe7a 1785
e1636f82 1786 if (!shouldValidate()) {
ad75fdbd 1787 return;
70b3fe7a
RG
1788 }
1789
70b3fe7a
RG
1790 DNSName qname(end);
1791 std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
1792
ad75fdbd 1793 bool oldSkipCNAME = d_skipCNAMECheck;
ad75fdbd 1794 d_skipCNAMECheck = true;
ad75fdbd 1795
70b3fe7a 1796 while(qname != begin) {
70b3fe7a
RG
1797 if (labelsToAdd.empty())
1798 break;
1799
1800 qname.prependRawLabel(labelsToAdd.back());
1801 labelsToAdd.pop_back();
bcb05770
RG
1802 LOG(d_prefix<<": - Looking for a cut at "<<qname<<endl);
1803
1804 const auto cutIt = d_cutStates.find(qname);
1805 if (cutIt != d_cutStates.cend()) {
1806 if (cutIt->second != Indeterminate) {
1807 LOG(d_prefix<<": - Cut already known at "<<qname<<endl);
3d4e836e 1808 cutState = cutIt->second;
bcb05770
RG
1809 continue;
1810 }
1811 }
70b3fe7a 1812
3d4e836e
RG
1813 /* no need to look for NS and DS if we are already insecure or bogus,
1814 just look for (N)TA
1815 */
1816 if (cutState == Insecure || cutState == Bogus) {
2010ac95
RG
1817 dsmap_t cutDS;
1818 vState newState = getDSRecords(qname, cutDS, true, depth);
3d4e836e
RG
1819 if (newState == Indeterminate) {
1820 continue;
1821 }
1822
1823 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[newState]<<endl);
3d4e836e
RG
1824 cutState = newState;
1825
1826 d_cutStates[qname] = cutState;
1827
1828 continue;
1829 }
70b3fe7a 1830
c405e222 1831 vState newState = Indeterminate;
428f41b7
RG
1832 /* temporarily mark as Indeterminate, so that we won't enter an endless loop
1833 trying to determine that zone cut again. */
c405e222
RG
1834 d_cutStates[qname] = newState;
1835 bool foundCut = lookForCut(qname, depth + 1, cutState, newState);
1836 if (foundCut) {
1837 LOG(d_prefix<<": - Found cut at "<<qname<<endl);
1838 if (newState != Indeterminate) {
1839 cutState = newState;
70b3fe7a 1840 }
c405e222
RG
1841 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[cutState]<<endl);
1842 d_cutStates[qname] = cutState;
70b3fe7a 1843 }
c405e222 1844 else {
428f41b7 1845 /* remove the temporary cut */
b25712fd 1846 LOG(d_prefix<<qname<<": removing cut state for "<<qname<<endl);
51b6b728 1847 d_cutStates.erase(qname);
428f41b7 1848 }
70b3fe7a
RG
1849 }
1850
ad75fdbd 1851 d_skipCNAMECheck = oldSkipCNAME;
ad75fdbd 1852
bcb05770 1853 LOG(d_prefix<<": list of cuts from "<<begin<<" to "<<end<<endl);
51b6b728 1854 for (const auto& cut : d_cutStates) {
bcb05770 1855 if (cut.first.isRoot() || (begin.isPartOf(cut.first) && cut.first.isPartOf(end))) {
51b6b728
RG
1856 LOG(" - "<<cut.first<<": "<<vStates[cut.second]<<endl);
1857 }
70b3fe7a 1858 }
4d2be65d
RG
1859}
1860
51b6b728 1861vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth)
4d2be65d
RG
1862{
1863 dsmap_t ds;
1864 if (!signatures.empty()) {
1865 DNSName signer = getSigner(signatures);
1866
8d2e7fa1 1867 if (!signer.empty() && zone.isPartOf(signer)) {
51b6b728 1868 vState state = getDSRecords(signer, ds, false, depth);
b7f378d1 1869
4d2be65d
RG
1870 if (state != Secure) {
1871 return state;
1872 }
1873 }
1874 }
1875
1876 skeyset_t tentativeKeys;
1877 std::vector<shared_ptr<DNSRecordContent> > toSign;
1878
1879 for (const auto& dnskey : dnskeys) {
1880 if (dnskey.d_type == QType::DNSKEY) {
1881 auto content = getRR<DNSKEYRecordContent>(dnskey);
1882 if (content) {
1883 tentativeKeys.insert(content);
1884 toSign.push_back(content);
1885 }
1886 }
1887 }
1888
bcb05770 1889 LOG(d_prefix<<": trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
4d2be65d
RG
1890 skeyset_t validatedKeys;
1891 validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
1892
bcb05770 1893 LOG(d_prefix<<": we now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
4d2be65d 1894
82fbd934
RG
1895 /* if we found at least one valid RRSIG covering the set,
1896 all tentative keys are validated keys. Otherwise it means
1897 we haven't found at least one DNSKEY and a matching RRSIG
1898 covering this set, this looks Bogus. */
4d2be65d 1899 if (validatedKeys.size() != tentativeKeys.size()) {
bcb05770 1900 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
4d2be65d
RG
1901 return Bogus;
1902 }
1903
1904 return Secure;
1905}
1906
51b6b728 1907vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth)
4d2be65d
RG
1908{
1909 std::vector<DNSRecord> records;
1910 std::set<GetBestNSAnswer> beenthere;
bcb05770 1911 LOG(d_prefix<<"Retrieving DNSKeys for "<<signer<<endl);
4d2be65d
RG
1912
1913 vState state = Indeterminate;
c7385ddb
RG
1914 /* following CNAME might lead to us to the wrong DNSKEY */
1915 bool oldSkipCNAME = d_skipCNAMECheck;
1916 d_skipCNAMECheck = true;
51b6b728 1917 int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state);
c7385ddb 1918 d_skipCNAMECheck = oldSkipCNAME;
4d2be65d
RG
1919
1920 if (rcode == RCode::NoError) {
1921 if (state == Secure) {
1922 for (const auto& key : records) {
1923 if (key.d_type == QType::DNSKEY) {
1924 auto content = getRR<DNSKEYRecordContent>(key);
1925 if (content) {
1926 keys.insert(content);
1927 }
1928 }
1929 }
1930 }
bcb05770 1931 LOG(d_prefix<<"Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<vStates[state]<<endl);
4d2be65d
RG
1932 return state;
1933 }
1934
bcb05770 1935 LOG(d_prefix<<"Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
4d2be65d
RG
1936 return Bogus;
1937}
1938
51b6b728 1939vState 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
1940{
1941 skeyset_t keys;
1942 if (!signatures.empty()) {
1943 const DNSName signer = getSigner(signatures);
1944 if (!signer.empty() && name.isPartOf(signer)) {
f715542c 1945 if ((qtype == QType::DNSKEY || qtype == QType::DS) && signer == qname) {
15f44f1d
RG
1946 /* we are already retrieving those keys, sorry */
1947 return Indeterminate;
1948 }
51b6b728 1949 vState state = getDNSKeys(signer, keys, depth);
4d2be65d
RG
1950 if (state != Secure) {
1951 return state;
1952 }
1953 }
1954 } else {
bcb05770 1955 LOG(d_prefix<<"Bogus!"<<endl);
4d2be65d
RG
1956 return Bogus;
1957 }
1958
1959 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
1960 for (const auto& record : records) {
1961 recordcontents.push_back(record.d_content);
1962 }
1963
bcb05770 1964 LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
4d2be65d 1965 if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
bcb05770 1966 LOG(d_prefix<<"Secure!"<<endl);
4d2be65d
RG
1967 return Secure;
1968 }
1969
bcb05770 1970 LOG(d_prefix<<"Bogus!"<<endl);
4d2be65d
RG
1971 return Bogus;
1972}
1973
e4894ce0 1974RCode::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)
4d2be65d 1975{
26ca3513
RG
1976 tcache_t tcache;
1977
4d2be65d
RG
1978 string prefix;
1979 if(doLog()) {
1980 prefix=d_prefix;
1981 prefix.append(depth, ' ');
1982 }
1983
2b984251 1984 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
142ab370 1985 const unsigned int labelCount = qname.countLabels();
a82d4e27 1986 bool isCNAMEAnswer = false;
26ca3513 1987 for(const auto& rec : lwr.d_records) {
c5310862
RG
1988 if (rec.d_class != QClass::IN) {
1989 continue;
1990 }
1991
a82d4e27
RG
1992 if(!isCNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
1993 isCNAMEAnswer = true;
1994 }
1995
9b061cf5
RG
1996 /* if we have a positive answer synthetized from a wildcard,
1997 we need to store the corresponding NSEC/NSEC3 records proving
1998 that the exact name did not exist in the negative cache */
2b984251
RG
1999 if(needWildcardProof) {
2000 if (nsecTypes.count(rec.d_type)) {
2001 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
2002 }
2003 else if (rec.d_type == QType::RRSIG) {
2004 auto rrsig = getRR<RRSIGRecordContent>(rec);
2005 if (rrsig && nsecTypes.count(rrsig->d_type)) {
2006 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
2007 }
2008 }
2009 }
26ca3513
RG
2010 if(rec.d_type == QType::RRSIG) {
2011 auto rrsig = getRR<RRSIGRecordContent>(rec);
2012 if (rrsig) {
bb07ad8e
RG
2013 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
2014 count can be lower than the name's label count if it was
9b061cf5 2015 synthetized from the wildcard. Note that the difference might
bb07ad8e
RG
2016 be > 1. */
2017 if (rec.d_name == qname && rrsig->d_labels < labelCount) {
9b061cf5 2018 LOG(prefix<<qname<<": RRSIG indicates the name was synthetized from a wildcard, we need a wildcard proof"<<endl);
2b984251 2019 needWildcardProof = true;
e4894ce0 2020 wildcardLabelsCount = rrsig->d_labels;
2b984251
RG
2021 }
2022
26ca3513
RG
2023 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
2024 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
4d2be65d 2025 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
2026 }
2027 }
2028 }
2029
2030 // reap all answers from this packet that are acceptable
2031 for(auto& rec : lwr.d_records) {
2032 if(rec.d_type == QType::OPT) {
2033 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
2034 continue;
2035 }
e77f01d1 2036 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 2037 if(rec.d_type == QType::ANY) {
c5310862
RG
2038 LOG("NO! - we don't accept 'ANY'-typed data"<<endl);
2039 continue;
2040 }
2041
2042 if(rec.d_class != QClass::IN) {
2043 LOG("NO! - we don't accept records for any other class than 'IN'"<<endl);
26ca3513
RG
2044 continue;
2045 }
2046
2047 if(rec.d_name.isPartOf(auth)) {
2048 if(rec.d_type == QType::RRSIG) {
2049 LOG("RRSIG - separate"<<endl);
2050 }
4d2be65d 2051 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
2052 LOG("NO! Is from delegation-only zone"<<endl);
2053 s_nodelegated++;
2054 return RCode::NXDomain;
2055 }
2056 else {
2057 bool haveLogged = false;
a712cb56 2058 if (!t_sstorage.domainmap->empty()) {
26ca3513
RG
2059 // Check if we are authoritative for a zone in this answer
2060 DNSName tmp_qname(rec.d_name);
2061 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
a712cb56 2062 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
26ca3513
RG
2063 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
2064 if (auth_domain_iter->first != auth) {
2065 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
2066 continue;
2067 } else {
2068 LOG("YES! - This answer was ");
6dfff36f 2069 if (!wasForwarded) {
26ca3513
RG
2070 LOG("retrieved from the local auth store.");
2071 } else {
2072 LOG("received from a server we forward to.");
2073 }
2074 haveLogged = true;
2075 LOG(endl);
2076 }
2077 }
2078 }
2079 if (!haveLogged) {
2080 LOG("YES!"<<endl);
2081 }
2082
2083 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
2084
2085 DNSRecord dr(rec);
26ca3513 2086 dr.d_ttl += d_now.tv_sec;
2b984251 2087 dr.d_place=DNSResourceRecord::ANSWER;
26ca3513
RG
2088 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
2089 }
2090 }
2091 else
2092 LOG("NO!"<<endl);
2093 }
2094
2095 // supplant
4d2be65d
RG
2096 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2097 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)
2098 uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
26ca3513
RG
2099
2100 for(auto& record : i->second.records)
4d2be65d 2101 record.d_ttl = lowestTTD; // boom
26ca3513
RG
2102 }
2103
2104// cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
2105// cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
4d2be65d
RG
2106 }
2107
2108 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
4d2be65d 2109
26ca3513
RG
2110 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
2111 continue;
6dfff36f 2112
405a26bd
RG
2113 /* Even if the AA bit is set, additional data cannot be considered
2114 as authoritative. This is especially important during validation
2115 because keeping records in the additional section is allowed even
2116 if the corresponding RRSIGs are not included, without setting the TC
2117 bit, as stated in rfc4035's section 3.1.1. Including RRSIG RRs in a Response:
2118 "When placing a signed RRset in the Additional section, the name
2119 server MUST also place its RRSIG RRs in the Additional section.
2120 If space does not permit inclusion of both the RRset and its
2121 associated RRSIG RRs, the name server MAY retain the RRset while
2122 dropping the RRSIG RRs. If this happens, the name server MUST NOT
2123 set the TC bit solely because these RRSIG RRs didn't fit."
2124 */
2125 bool isAA = lwr.d_aabit && i->first.place != DNSResourceRecord::ADDITIONAL;
cdc5d0c0 2126 if (isAA && isCNAMEAnswer && i->first.place == DNSResourceRecord::ANSWER && (i->first.type != QType::CNAME || i->first.name != qname)) {
a82d4e27
RG
2127 /*
2128 rfc2181 states:
2129 Note that the answer section of an authoritative answer normally
2130 contains only authoritative data. However when the name sought is an
2131 alias (see section 10.1.1) only the record describing that alias is
2132 necessarily authoritative. Clients should assume that other records
2133 may have come from the server's cache. Where authoritative answers
2134 are required, the client should query again, using the canonical name
2135 associated with the alias.
2136 */
2137 isAA = false;
2138 }
2139
5374b03b 2140 vState recordState = getValidationStatus(i->first.name, false);
1a8d6a9e 2141 LOG(d_prefix<<": got initial zone status "<<vStates[recordState]<<" for record "<<i->first.name<<"|"<<DNSRecordContent::NumberToType(i->first.type)<<endl);
70b3fe7a 2142
e1636f82 2143 if (shouldValidate() && recordState == Secure) {
5374b03b
RG
2144 vState initialState = recordState;
2145
a82d4e27 2146 if (isAA) {
4d2be65d
RG
2147 if (i->first.place != DNSResourceRecord::ADDITIONAL) {
2148 /* the additional entries can be insecure,
2149 like glue:
2150 "Glue address RRsets associated with delegations MUST NOT be signed"
2151 */
2152 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) {
bcb05770 2153 LOG(d_prefix<<"Validating DNSKEY for "<<i->first.name<<endl);
51b6b728 2154 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth);
4d2be65d
RG
2155 }
2156 else {
bcb05770 2157 LOG(d_prefix<<"Validating non-additional record for "<<i->first.name<<endl);
51b6b728 2158 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
0735b60f
RG
2159 /* 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 */
2160 if (qtype == QType::NS && i->second.signatures.empty() && recordState == Bogus && haveExactValidationStatus(i->first.name) && getValidationStatus(i->first.name) == Indeterminate) {
2161 recordState = Indeterminate;
2162 }
4d2be65d
RG
2163 }
2164 }
2165 }
2166 else {
933299e8
RG
2167 recordState = Indeterminate;
2168
a82d4e27 2169 /* in a non authoritative answer, we only care about the DS record (or lack of) */
88cb0fe0 2170 if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
bcb05770 2171 LOG(d_prefix<<"Validating DS record for "<<i->first.name<<endl);
51b6b728 2172 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
4d2be65d
RG
2173 }
2174 }
0735b60f 2175
933299e8 2176 if (initialState == Secure && state != recordState && isAA) {
5374b03b
RG
2177 updateValidationState(state, recordState);
2178 }
4d2be65d
RG
2179 }
2180 else {
e1636f82 2181 if (shouldValidate()) {
bcb05770 2182 LOG(d_prefix<<"Skipping validation because the current state is "<<vStates[recordState]<<endl);
4d2be65d
RG
2183 }
2184 }
2185
005b4b98
RG
2186 /* We don't need to store NSEC3 records in the positive cache because:
2187 - we don't allow direct NSEC3 queries
2188 - denial of existence proofs in wildcard expanded positive responses are stored in authorityRecs
2189 - denial of existence proofs for negative responses are stored in the negative cache
2190 */
2191 if (i->first.type != QType::NSEC3) {
142ab370 2192 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 2193 }
6dfff36f 2194
26ca3513
RG
2195 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
2196 d_wasVariable=true;
2197 }
2198
2199 return RCode::NoError;
2200}
2201
28364e4b 2202void SyncRes::updateDenialValidationState(vState& neValidationState, const DNSName& neName, vState& state, const dState denialState, const dState expectedState, bool allowOptOut)
4d2be65d 2203{
b25712fd 2204 if (denialState == expectedState) {
28364e4b 2205 neValidationState = Secure;
b25712fd
RG
2206 }
2207 else {
142ab370 2208 if (denialState == OPTOUT && allowOptOut) {
28364e4b
RG
2209 LOG(d_prefix<<"OPT-out denial found for "<<neName<<endl);
2210 neValidationState = Secure;
142ab370 2211 return;
4d2be65d 2212 }
142ab370 2213 else if (denialState == INSECURE) {
28364e4b
RG
2214 LOG(d_prefix<<"Insecure denial found for "<<neName<<", returning Insecure"<<endl);
2215 neValidationState = Insecure;
4d2be65d 2216 }
142ab370 2217 else {
28364e4b
RG
2218 LOG(d_prefix<<"Invalid denial found for "<<neName<<", returning Bogus, res="<<denialState<<", expectedState="<<expectedState<<endl);
2219 neValidationState = Bogus;
142ab370 2220 }
28364e4b 2221 updateValidationState(state, neValidationState);
4d2be65d
RG
2222 }
2223}
2224
28364e4b 2225dState SyncRes::getDenialValidationState(const NegCache::NegCacheEntry& ne, const vState state, const dState expectedState, bool referralToUnsigned)
142ab370
RG
2226{
2227 cspmap_t csp = harvestCSPFromNE(ne);
2228 return getDenial(csp, ne.d_name, ne.d_qtype.getCode(), referralToUnsigned, expectedState == NXQTYPE);
2229}
2230
e4894ce0 2231bool 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
2232{
2233 bool done = false;
2234
2235 for(auto& rec : lwr.d_records) {
2236 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
2237 continue;
2238
2239 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2240 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
2241 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
2242
2243 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
2244 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
2245 ret.push_back(rec);
39ce10b2 2246
114829cc
RG
2247 NegCache::NegCacheEntry ne;
2248
dbbef467 2249 uint32_t lowestTTL = rec.d_ttl;
9b061cf5
RG
2250 /* if we get an NXDomain answer with a CNAME, the name
2251 does exist but the target does not */
2252 ne.d_name = newtarget.empty() ? qname : newtarget;
114829cc
RG
2253 ne.d_qtype = QType(0); // this encodes 'whole record'
2254 ne.d_auth = rec.d_name;
dbbef467
RG
2255 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2256 ne.d_ttd = d_now.tv_sec + lowestTTL;
2257
142ab370
RG
2258 if (state == Secure) {
2259 dState denialState = getDenialValidationState(ne, state, NXDOMAIN, false);
28364e4b 2260 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, NXDOMAIN, false);
142ab370
RG
2261 }
2262 else {
2263 ne.d_validationState = state;
2264 }
114829cc 2265
9b061cf5
RG
2266 /* if we get an NXDomain answer with a CNAME, let's not cache the
2267 target, even the server was authoritative for it,
2268 and do an additional query for the CNAME target.
2269 We have a regression test making sure we do exactly that.
2270 */
2271 if(!wasVariable() && newtarget.empty()) {
a712cb56 2272 t_sstorage.negcache.add(ne);
07e3cfb6 2273 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
9a1e060b 2274 ne.d_name = ne.d_name.getLastLabel();
a712cb56 2275 t_sstorage.negcache.add(ne);
26ca3513
RG
2276 }
2277 }
2278
2279 negindic=true;
2280 }
4d2be65d 2281 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
26ca3513
RG
2282 ret.push_back(rec);
2283 if (auto content = getRR<CNAMERecordContent>(rec)) {
2284 newtarget=content->getTarget();
2285 }
2286 }
9b061cf5
RG
2287 /* if we have a positive answer synthetized from a wildcard, we need to
2288 return the corresponding NSEC/NSEC3 records from the AUTHORITY section
2289 proving that the exact name did not exist */
2b984251
RG
2290 else if(needWildcardProof && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::AUTHORITY) {
2291 ret.push_back(rec); // enjoy your DNSSEC
2292 }
26ca3513
RG
2293 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
2294 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
2295 (
331222c4 2296 rec.d_type==qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType(QType::ANY))
26ca3513
RG
2297 )
2298 )
2299 {
2300 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
2301
2302 done=true;
2303 ret.push_back(rec);
9b061cf5
RG
2304
2305 if (state == Secure && needWildcardProof) {
2306 /* We have a positive answer synthetized from a wildcard, we need to check that we have
2307 proof that the exact name doesn't exist so the wildcard can be used,
2308 as described in section 5.3.4 of RFC 4035 and 5.3 of FRC 7129.
2309 */
2310 NegCache::NegCacheEntry ne;
2311
2312 uint32_t lowestTTL = rec.d_ttl;
2313 ne.d_name = qname;
2314 ne.d_qtype = QType(0); // this encodes 'whole record'
2315 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2316
2317 cspmap_t csp = harvestCSPFromNE(ne);
e4894ce0 2318 dState res = getDenial(csp, qname, ne.d_qtype.getCode(), false, false, false, wildcardLabelsCount);
9b061cf5 2319 if (res != NXDOMAIN) {
b7c40613
RG
2320 vState st = Bogus;
2321 if (res == INSECURE) {
2322 /* Some part could not be validated, for example a NSEC3 record with a too large number of iterations,
2323 this is not enough to warrant a Bogus, but go Insecure. */
2324 st = Insecure;
2325 LOG(d_prefix<<"Unable to validate denial in wildcard expanded positive response found for "<<qname<<", returning Insecure, res="<<res<<endl);
2326 }
2327 else {
2328 LOG(d_prefix<<"Invalid denial in wildcard expanded positive response found for "<<qname<<", returning Bogus, res="<<res<<endl);
2329 }
2330
2331 updateValidationState(state, st);
2332 /* we already stored the record with a different validation status, let's fix it */
2fe3354d 2333 t_RC->updateValidationStatus(d_now.tv_sec, qname, qtype, d_cacheRemote, lwr.d_aabit, st);
9b061cf5
RG
2334 }
2335 }
26ca3513 2336 }
7030a59b
RG
2337 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER) {
2338 if(rec.d_type != QType::RRSIG || rec.d_name == qname)
2339 ret.push_back(rec); // enjoy your DNSSEC
2340 }
4d2be65d 2341 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::NS && qname.isPartOf(rec.d_name)) {
26ca3513
RG
2342 if(moreSpecificThan(rec.d_name,auth)) {
2343 newauth=rec.d_name;
2344 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2345 realreferral=true;
2346 }
2347 else {
2348 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
2349 }
2350 if (auto content = getRR<NSRecordContent>(rec)) {
2351 nsset.insert(content->getNS());
2352 }
2353 }
4d2be65d 2354 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
26ca3513 2355 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
26ca3513 2356 }
860d5e8e 2357 else if(realreferral && rec.d_place==DNSResourceRecord::AUTHORITY && (rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && newauth.isPartOf(auth)) {
4d2be65d
RG
2358 /* we might have received a denial of the DS, let's check */
2359 if (state == Secure) {
2360 NegCache::NegCacheEntry ne;
2361 ne.d_auth = auth;
860d5e8e
RG
2362 ne.d_name = newauth;
2363 ne.d_qtype = QType::DS;
dbbef467
RG
2364 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2365 uint32_t lowestTTL = rec.d_ttl;
2366 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2367
142ab370
RG
2368 dState denialState = getDenialValidationState(ne, state, NXQTYPE, true);
2369
d377bb54 2370 if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
dbbef467 2371 ne.d_ttd = lowestTTL + d_now.tv_sec;
860d5e8e 2372 ne.d_validationState = Secure;
812c3a69 2373 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
5374b03b 2374
4d2be65d
RG
2375 if(!wasVariable()) {
2376 t_sstorage.negcache.add(ne);
2377 }
5374b03b
RG
2378
2379 if (qname == newauth && qtype == QType::DS) {
2380 /* we are actually done! */
2381 negindic=true;
2382 nsset.clear();
2383 }
4d2be65d
RG
2384 }
2385 }
2386 }
2387 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2388 lwr.d_rcode==RCode::NoError && qname.isPartOf(rec.d_name)) {
26ca3513
RG
2389 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
2390
2391 if(!newtarget.empty()) {
2392 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
2393 }
2394 else {
2395 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2396 ret.push_back(rec);
114829cc
RG
2397
2398 NegCache::NegCacheEntry ne;
2399 ne.d_auth = rec.d_name;
dbbef467 2400 uint32_t lowestTTL = rec.d_ttl;
114829cc
RG
2401 ne.d_name = qname;
2402 ne.d_qtype = qtype;
dbbef467
RG
2403 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2404 ne.d_ttd = d_now.tv_sec + lowestTTL;
2405
142ab370
RG
2406 if (state == Secure) {
2407 dState denialState = getDenialValidationState(ne, state, NXQTYPE, false);
28364e4b 2408 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, NXQTYPE, qtype == QType::DS);
142ab370
RG
2409 } else {
2410 ne.d_validationState = state;
2411 }
114829cc 2412
26ca3513 2413 if(!wasVariable()) {
26ca3513 2414 if(qtype.getCode()) { // prevents us from blacking out a whole domain
a712cb56 2415 t_sstorage.negcache.add(ne);
26ca3513
RG
2416 }
2417 }
2418 negindic=true;
2419 }
2420 }
2421 }
2422
2423 return done;
2424}
2425
6dfff36f
RG
2426bool 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)
2427{
deca7d8f 2428 bool chained = false;
17cecc84 2429 int resolveret = RCode::NoError;
6dfff36f
RG
2430 s_outqueries++;
2431 d_outqueries++;
2432
2433 if(d_outqueries + d_throttledqueries > s_maxqperq) {
2434 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
2435 }
2436
2437 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
2438 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");
2439 }
2440
2441 if(doTCP) {
2442 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
2443 s_tcpoutqueries++;
2444 d_tcpoutqueries++;
2445 }
2446
2447 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
2448 LOG(prefix<<qname<<": query handled by Lua"<<endl);
2449 }
2450 else {
2fe3354d 2451 ednsmask=getEDNSSubnetMask(qname, remoteIP);
6dfff36f
RG
2452 if(ednsmask) {
2453 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
d6923beb 2454 s_ecsqueries++;
6dfff36f
RG
2455 }
2456 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(),
deca7d8f 2457 doTCP, sendRDQuery, &d_now, ednsmask, &lwr, &chained); // <- we go out on the wire!
6dfff36f 2458 if(ednsmask) {
d6923beb 2459 s_ecsresponses++;
6dfff36f
RG
2460 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
2461 }
2462 }
2463
2464 /* preoutquery killed the query by setting dq.rcode to -3 */
2465 if(resolveret==-3) {
2466 throw ImmediateServFailException("Query killed by policy");
2467 }
2468
2469 d_totUsec += lwr.d_usec;
2470 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
2471
2472 if(resolveret != 1) {
2473 /* Error while resolving */
2474 if(resolveret == 0) {
2475 /* Time out */
2476
2477 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
2478 d_timeouts++;
2479 s_outgoingtimeouts++;
2480
2481 if(remoteIP.sin4.sin_family == AF_INET)
2482 s_outgoing4timeouts++;
2483 else
2484 s_outgoing6timeouts++;
be9078b3 2485
2486 if(t_timeouts)
2487 t_timeouts->push_back(remoteIP);
6dfff36f
RG
2488 }
2489 else if(resolveret == -2) {
2490 /* OS resource limit reached */
2491 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
2492 g_stats.resourceLimits++;
2493 }
2494 else {
2495 /* -1 means server unreachable */
2496 s_unreachables++;
2497 d_unreachables++;
2498 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
2499 }
2500
deca7d8f 2501 if(resolveret != -2 && !chained) { // don't account for resource limits, they are our own fault
589884b8 2502 t_sstorage.nsSpeeds[nsName.empty()? DNSName(remoteIP.toStringWithPort()) : nsName].submit(remoteIP, 1000000, &d_now); // 1 sec
6dfff36f
RG
2503
2504 // code below makes sure we don't filter COM or the root
2505 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) {
2506 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
2507 // mark server as down
2508 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
2509 }
2510 else if (resolveret == -1) {
2511 // unreachable, 1 minute or 100 queries
2512 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
2513 }
2514 else {
2515 // timeout
2516 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
2517 }
2518 }
2519
2520 return false;
2521 }
2522
2523 /* we got an answer */
2524 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
2525 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
deca7d8f
RG
2526 if (!chained) {
2527 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2528 }
6dfff36f
RG
2529 return false;
2530 }
2531
2532 /* this server sent a valid answer, mark it backup up if it was down */
2533 if(s_serverdownmaxfails > 0) {
2534 t_sstorage.fails.clear(remoteIP);
2535 }
2536
2537 if(lwr.d_tcbit) {
2538 *truncated = true;
2539
2540 if (doTCP) {
2541 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
2542 /* let's treat that as a ServFail answer from this server */
2543 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2544 return false;
2545 }
2546
2547 return true;
2548 }
2549
2550 return true;
2551}
2552
51b6b728 2553bool 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
2554{
2555 string prefix;
2556 if(doLog()) {
2557 prefix=d_prefix;
2558 prefix.append(depth, ' ');
2559 }
2560
2561 if(s_minimumTTL) {
2562 for(auto& rec : lwr.d_records) {
2563 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
2564 }
2565 }
2566
2b984251 2567 bool needWildcardProof = false;
e4894ce0
RG
2568 unsigned int wildcardLabelsCount;
2569 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, needWildcardProof, wildcardLabelsCount);
6dfff36f
RG
2570 if (*rcode != RCode::NoError) {
2571 return true;
2572 }
2573
2574 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
2575
2576 set<DNSName> nsset;
2577 bool realreferral=false, negindic=false;
2578 DNSName newauth;
2579 DNSName newtarget;
2580
e4894ce0 2581 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof, wildcardLabelsCount);
6dfff36f
RG
2582
2583 if(done){
2584 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
5374b03b 2585 LOG(prefix<<qname<<": validation status is "<<vStates[state]<<endl);
6dfff36f
RG
2586 *rcode = RCode::NoError;
2587 return true;
2588 }
2589
2590 if(!newtarget.empty()) {
2591 if(newtarget == qname) {
2592 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
2593 *rcode = RCode::ServFail;
2594 return true;
2595 }
2596
2597 if(depth > 10) {
2598 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
2599 *rcode = RCode::ServFail;
2600 return true;
2601 }
2602
5374b03b
RG
2603 if (qtype == QType::DS) {
2604 LOG(prefix<<qname<<": status=got a CNAME referral, but we are looking for a DS"<<endl);
6dfff36f 2605
1c39e884
RG
2606 if(d_doDNSSEC)
2607 addNXNSECS(ret, lwr.d_records);
2608
2609 *rcode = RCode::NoError;
2610 return true;
5374b03b
RG
2611 }
2612 else {
2613 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
6dfff36f 2614
5374b03b
RG
2615 set<GetBestNSAnswer> beenthere2;
2616 vState cnameState = Indeterminate;
2617 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState);
2618 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
2619 updateValidationState(state, cnameState);
2620 return true;
2621 }
6dfff36f
RG
2622 }
2623
2624 if(lwr.d_rcode == RCode::NXDomain) {
2625 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
2626
2627 if(d_doDNSSEC)
2628 addNXNSECS(ret, lwr.d_records);
2629
2630 *rcode = RCode::NXDomain;
2631 return true;
2632 }
2633
2634 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
2635 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
2636
114829cc
RG
2637 if(state == Secure && lwr.d_aabit && !negindic) {
2638 updateValidationState(state, Bogus);
2639 }
2640
6dfff36f
RG
2641 if(d_doDNSSEC)
2642 addNXNSECS(ret, lwr.d_records);
2643
2644 *rcode = RCode::NoError;
2645 return true;
2646 }
2647
2648 if(realreferral) {
2649 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
6dfff36f
RG
2650
2651 nameservers.clear();
2652 for (auto const &nameserver : nsset) {
2653 if (d_wantsRPZ) {
2654 d_appliedPolicy = dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
2655 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2656 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
2657 *rcode = -2;
2658 return true;
2659 }
2660 }
2661 nameservers.insert({nameserver, {{}, false}});
2662 }
2663 LOG("looping to them"<<endl);
2664 *gotNewServers = true;
812c3a69 2665 auth=newauth;
4d2be65d 2666
6dfff36f
RG
2667 return false;
2668 }
2669
2670 return false;
2671}
2672
b8470add
PL
2673/** returns:
2674 * -1 in case of no results
2675 * -2 when a FilterEngine Policy was hit
2676 * rcode otherwise
2677 */
fa1b87ff 2678int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
e325f20c 2679 vector<DNSRecord>&ret,
51b6b728 2680 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state)
86c152f2 2681{
69cbdef9 2682 auto luaconfsLocal = g_luaconfs.getLocal();
ded77b10 2683 string prefix;
77499b05 2684 if(doLog()) {
ded77b10
BH
2685 prefix=d_prefix;
2686 prefix.append(depth, ' ');
2687 }
3ddb9247 2688
b8470add
PL
2689 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
2690
69cbdef9 2691 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
26ca3513 2692 return -2;
b8470add
PL
2693 }
2694
2695 LOG(endl);
afbe2787
BH
2696
2697 for(;;) { // we may get more specific nameservers
e8b23f3b 2698 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
3ddb9247 2699
26ca3513
RG
2700 for(auto tns=rnameservers.cbegin();;++tns) {
2701 if(tns==rnameservers.cend()) {
2189085d 2702 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
03c09afe 2703 if(!auth.isRoot() && flawedNSSet) {
2189085d 2704 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
88490c03 2705
49a699c4 2706 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
4957a608
BH
2707 g_stats.nsSetInvalidations++;
2708 }
2709 return -1;
afbe2787 2710 }
6dfff36f 2711
b4c8789a
RG
2712 bool cacheOnly = false;
2713 // this line needs to identify the 'self-resolving' behaviour
2714 if(qname == *tns && (qtype.getCode() == QType::A || qtype.getCode() == QType::AAAA)) {
2715 /* we might have a glue entry in cache so let's try this NS
2716 but only if we have enough in the cache to know how to reach it */
2717 LOG(prefix<<qname<<": Using NS to resolve itself, but only using what we have in cache ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
2718 cacheOnly = true;
20177d1d 2719 }
5605c067 2720
996c89cc 2721 typedef vector<ComboAddress> remoteIPs_t;
5605c067 2722 remoteIPs_t remoteIPs;
bfea0d0b 2723 remoteIPs_t::const_iterator remoteIP;
1c21f389 2724 bool pierceDontQuery=false;
c1d73d94 2725 bool sendRDQuery=false;
376effcf 2726 boost::optional<Netmask> ednsmask;
263f6a5a 2727 LWResult lwr;
6dfff36f
RG
2728 const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty());
2729 int rcode = RCode::NoError;
2730 bool gotNewServers = false;
2731
2732 if(tns->empty() && !wasForwarded) {
2189085d 2733 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
e1636f82
RG
2734 /* setting state to indeterminate since validation is disabled for local auth zone,
2735 and Insecure would be misleading. */
2736 state = Indeterminate;
9fc36e90 2737 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
4957a608
BH
2738 lwr.d_tcbit=false;
2739 lwr.d_aabit=true;
6dfff36f
RG
2740
2741 /* we have received an answer, are we done ? */
51b6b728 2742 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
6dfff36f
RG
2743 if (done) {
2744 return rcode;
2745 }
2746 if (gotNewServers) {
2747 break;
2748 }
5605c067
BH
2749 }
2750 else {
6dfff36f 2751 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
b4c8789a 2752 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly);
4957a608
BH
2753
2754 if(remoteIPs.empty()) {
2189085d 2755 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
4957a608
BH
2756 flawedNSSet=true;
2757 continue;
2758 }
2759 else {
b8470add 2760 bool hitPolicy{false};
2189085d 2761 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
26ca3513
RG
2762 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2763 if(remoteIP != remoteIPs.cbegin()) {
77499b05
BH
2764 LOG(", ");
2765 }
2766 LOG(remoteIP->toString());
69cbdef9 2767 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
26ca3513 2768 hitPolicy = true;
b8470add 2769 }
4957a608 2770 }
77499b05 2771 LOG(endl);
b8470add
PL
2772 if (hitPolicy) //implies d_wantsRPZ
2773 return -2;
4957a608
BH
2774 }
2775
26ca3513 2776 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2189085d 2777 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
6dfff36f 2778
26ca3513 2779 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
4957a608
BH
2780 continue;
2781 }
9de3e034 2782
6dfff36f
RG
2783 bool truncated = false;
2784 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2785 *tns, *remoteIP, false, &truncated);
2786 if (gotAnswer && truncated ) {
2787 /* retry, over TCP this time */
2788 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2789 *tns, *remoteIP, true, &truncated);
2790 }
710af846 2791
6dfff36f
RG
2792 if (!gotAnswer) {
2793 continue;
2794 }
352b4183 2795
6dfff36f 2796 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 2797
6dfff36f
RG
2798 /* // for you IPv6 fanatics :-)
2799 if(remoteIP->sin4.sin_family==AF_INET6)
2800 lwr.d_usec/=3;
2801 */
2802 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
710af846 2803
589884b8 2804 t_sstorage.nsSpeeds[tns->empty()? DNSName(remoteIP->toStringWithPort()) : *tns].submit(*remoteIP, lwr.d_usec, &d_now);
628e2c7b 2805
6dfff36f 2806 /* we have received an answer, are we done ? */
51b6b728 2807 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
6dfff36f
RG
2808 if (done) {
2809 return rcode;
4957a608 2810 }
6dfff36f
RG
2811 if (gotNewServers) {
2812 break;
4957a608 2813 }
6dfff36f
RG
2814 /* was lame */
2815 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
4957a608 2816 }
aadceba8 2817
6dfff36f
RG
2818 if (gotNewServers) {
2819 break;
4957a608 2820 }
620db2c8 2821
6dfff36f
RG
2822 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
2823 continue;
620db2c8 2824
86c152f2
BH
2825 }
2826 }
86c152f2 2827 }
ac539791 2828 return -1;
86c152f2
BH
2829}
2830
2fe3354d 2831void SyncRes::setQuerySource(const ComboAddress& requestor, boost::optional<const EDNSSubnetOpts&> incomingECS)
8a3a3822 2832{
2fe3354d
CH
2833 d_requestor = requestor;
2834
2835 if (incomingECS && incomingECS->source.getBits() > 0) {
2836 d_cacheRemote = incomingECS->source.getMaskedNetwork();
2837 uint8_t bits = std::min(incomingECS->source.getBits(), (incomingECS->source.isIpv4() ? s_ecsipv4limit : s_ecsipv6limit));
2838 ComboAddress trunc = incomingECS->source.getNetwork();
2839 trunc.truncate(bits);
2840 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
2841 } else {
2842 d_cacheRemote = d_requestor;
2843 if(!incomingECS && s_ednslocalsubnets.match(d_requestor)) {
2844 ComboAddress trunc = d_requestor;
2845 uint8_t bits = d_requestor.isIPv4() ? 32 : 128;
2846 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
2847 trunc.truncate(bits);
2848 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
2849 } else if (s_ecsScopeZero.source.getBits() > 0) {
8a3a3822
RG
2850 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0.
2851 But using an empty ECS in that case would mean inserting
2852 a non ECS-specific entry into the cache, preventing any further
2853 ECS-specific query to be sent.
2854 So instead we use the trick described in section 7.1.2:
2855 "The subsequent Recursive Resolver query to the Authoritative Nameserver
2856 will then either not include an ECS option or MAY optionally include
2857 its own address information, which is what the Authoritative
2858 Nameserver will almost certainly use to generate any Tailored
2859 Response in lieu of an option. This allows the answer to be handled
2860 by the same caching mechanism as other queries, with an explicit
2861 indicator of the applicable scope. Subsequent Stub Resolver queries
2862 for /0 can then be answered from this cached response.
2863 */
2fe3354d
CH
2864 d_outgoingECSNetwork = boost::optional<Netmask>(s_ecsScopeZero.source.getMaskedNetwork());
2865 d_cacheRemote = s_ecsScopeZero.source.getNetwork();
2866 } else {
2867 // ECS disabled because no scope-zero address could be derived.
2868 d_outgoingECSNetwork = boost::none;
8a3a3822
RG
2869 }
2870 }
8a3a3822
RG
2871}
2872
2fe3354d 2873boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const DNSName& dn, const ComboAddress& rem)
e9f9b8ec 2874{
2fe3354d
CH
2875 if(d_outgoingECSNetwork && (s_ednsdomains.check(dn) || s_ednsremotesubnets.match(rem))) {
2876 return d_outgoingECSNetwork;
e9f9b8ec 2877 }
2fe3354d 2878 return boost::none;
e9f9b8ec 2879}
bd53ea9d 2880
9065eb05
RG
2881void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
2882{
2883 vector<string> parts;
2884 stringtok(parts, wlist, ",; ");
2885 for(const auto& a : parts) {
2886 try {
2fe3354d 2887 s_ednsremotesubnets.addMask(Netmask(a));
9065eb05
RG
2888 }
2889 catch(...) {
2890 s_ednsdomains.add(DNSName(a));
2891 }
2892 }
2893}
2894
2fe3354d
CH
2895void SyncRes::parseEDNSSubnetAddFor(const std::string& subnetlist)
2896{
2897 vector<string> parts;
2898 stringtok(parts, subnetlist, ",; ");
2899 for(const auto& a : parts) {
2900 s_ednslocalsubnets.addMask(a);
2901 }
2902}
2903
8ce79a22 2904// used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
a3e7b735 2905int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
bd53ea9d
PD
2906{
2907 struct timeval now;
2908 gettimeofday(&now, 0);
710af846 2909
bd53ea9d 2910 SyncRes sr(now);
13658071
RB
2911 int res = -1;
2912 try {
2913 res = sr.beginResolve(qname, QType(qtype), qclass, ret);
2914 }
2915 catch(const PDNSException& e) {
2916 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got pdns exception: "<<e.reason<<endl;
2917 ret.clear();
2918 }
2919 catch(const ImmediateServFailException& e) {
2920 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got ImmediateServFailException: "<<e.reason<<endl;
2921 ret.clear();
2922 }
2923 catch(const std::exception& e) {
2924 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got STL error: "<<e.what()<<endl;
2925 ret.clear();
2926 }
2927 catch(...) {
2928 g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got an exception"<<endl;
2929 ret.clear();
2930 }
e325f20c 2931
bd53ea9d
PD
2932 return res;
2933}
30ee601a 2934
30ee601a
RG
2935int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
2936 SyncRes sr(now);
2937 sr.setDoEDNS0(true);
0b29b9c5 2938 sr.setUpdatingRootNS();
30ee601a 2939 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
0c43f455 2940 sr.setDNSSECValidationRequested(g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate);
30ee601a
RG
2941 sr.setAsyncCallback(asyncCallback);
2942
2943 vector<DNSRecord> ret;
2944 int res=-1;
2945 try {
2946 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
2947 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
4d2be65d 2948 auto state = sr.getValidationState();
30ee601a
RG
2949 if (state == Bogus)
2950 throw PDNSException("Got Bogus validation result for .|NS");
2951 }
2952 return res;
2953 }
c78ceb39 2954 catch(const PDNSException& e) {
e6a9dde5 2955 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
30ee601a 2956 }
c78ceb39 2957 catch(const ImmediateServFailException& e) {
e6a9dde5 2958 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
c78ceb39
RG
2959 }
2960 catch(const std::exception& e) {
e6a9dde5 2961 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
30ee601a 2962 }
c78ceb39 2963 catch(...) {
e6a9dde5 2964 g_log<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
30ee601a 2965 }
c78ceb39 2966
30ee601a 2967 if(!res) {
e6a9dde5 2968 g_log<<Logger::Notice<<"Refreshed . records"<<endl;
30ee601a
RG
2969 }
2970 else
e6a9dde5 2971 g_log<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
c78ceb39 2972
30ee601a
RG
2973 return res;
2974}