]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/syncres.cc
rec: Primed root-servers.net is Insecure
[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"
4d2be65d 36#include "validate-recursor.hh"
6dfff36f 37
a712cb56 38thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage;
bb4bdbaf 39
3337c2f7
RG
40std::unordered_set<DNSName> SyncRes::s_delegationOnly;
41std::unique_ptr<NetmaskGroup> SyncRes::s_dontQuery{nullptr};
42NetmaskGroup SyncRes::s_ednssubnets;
43SuffixMatchNode SyncRes::s_ednsdomains;
44string SyncRes::s_serverID;
45SyncRes::LogMode SyncRes::s_lm;
46
a9af3782 47unsigned int SyncRes::s_maxnegttl;
c3e753c7 48unsigned int SyncRes::s_maxcachettl;
3337c2f7
RG
49unsigned int SyncRes::s_maxqperq;
50unsigned int SyncRes::s_maxtotusec;
51unsigned int SyncRes::s_maxdepth;
52unsigned int SyncRes::s_minimumTTL;
1051f8a9
BH
53unsigned int SyncRes::s_packetcachettl;
54unsigned int SyncRes::s_packetcacheservfailttl;
628e2c7b
PA
55unsigned int SyncRes::s_serverdownmaxfails;
56unsigned int SyncRes::s_serverdownthrottletime;
aebb81e4 57std::atomic<uint64_t> SyncRes::s_queries;
58std::atomic<uint64_t> SyncRes::s_outgoingtimeouts;
59std::atomic<uint64_t> SyncRes::s_outgoing4timeouts;
60std::atomic<uint64_t> SyncRes::s_outgoing6timeouts;
61std::atomic<uint64_t> SyncRes::s_outqueries;
62std::atomic<uint64_t> SyncRes::s_tcpoutqueries;
63std::atomic<uint64_t> SyncRes::s_throttledqueries;
64std::atomic<uint64_t> SyncRes::s_dontqueries;
65std::atomic<uint64_t> SyncRes::s_nodelegated;
66std::atomic<uint64_t> SyncRes::s_unreachables;
e9f9b8ec
RG
67uint8_t SyncRes::s_ecsipv4limit;
68uint8_t SyncRes::s_ecsipv6limit;
996c89cc 69bool SyncRes::s_doIPv6;
1051f8a9 70bool SyncRes::s_nopacketcache;
01402d56 71bool SyncRes::s_rootNXTrust;
3337c2f7 72bool SyncRes::s_noEDNS;
c836dc19 73
77499b05 74#define LOG(x) if(d_lm == Log) { L <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
728485ca 75
69cbdef9 76static void accountAuthLatency(int usec, int family)
11adfdd3 77{
7b75810e 78 if(family == AF_INET) {
79 if(usec < 1000)
80 g_stats.auth4Answers0_1++;
81 else if(usec < 10000)
82 g_stats.auth4Answers1_10++;
83 else if(usec < 100000)
84 g_stats.auth4Answers10_100++;
85 else if(usec < 1000000)
86 g_stats.auth4Answers100_1000++;
87 else
88 g_stats.auth4AnswersSlow++;
89 } else {
90 if(usec < 1000)
91 g_stats.auth6Answers0_1++;
92 else if(usec < 10000)
93 g_stats.auth6Answers1_10++;
94 else if(usec < 100000)
95 g_stats.auth6Answers10_100++;
96 else if(usec < 1000000)
97 g_stats.auth6Answers100_1000++;
98 else
99 g_stats.auth6AnswersSlow++;
100 }
101
11adfdd3 102}
103
4465e941 104
ac0e821b 105SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
30ee601a 106 d_totUsec(0), d_now(now),
0b29b9c5 107 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm)
232f0877 108
ac0e821b 109{
ac0e821b
BH
110}
111
728485ca 112/** everything begins here - this is the entry point just after receiving a packet */
e325f20c 113int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
728485ca 114{
4d2be65d 115 vState state = Indeterminate;
c836dc19 116 s_queries++;
3762e821 117 d_wasVariable=false;
9fc36e90 118 d_wasOutOfBand=false;
710af846 119
4d2be65d
RG
120 if (doSpecialNamesResolve(qname, qtype, qclass, ret)) {
121 d_queryValidationState = Secure;
db50a7f4 122 return 0;
4d2be65d 123 }
db50a7f4 124
fad4e1b2 125 if( (qtype.getCode() == QType::AXFR) || (qtype.getCode() == QType::IXFR))
693dbe65 126 return -1;
710af846 127
db50a7f4
PL
128 if(qclass==QClass::ANY)
129 qclass=QClass::IN;
130 else if(qclass!=QClass::IN)
131 return -1;
8171ab83 132
db50a7f4 133 set<GetBestNSAnswer> beenthere;
ad75fdbd
RG
134 SyncRes::zonesStates_t cuts;
135 int res=doResolve(qname, qtype, ret, 0, beenthere, state, cuts);
4d2be65d 136 d_queryValidationState = state;
db50a7f4
PL
137 return res;
138}
139
140/*! Handles all special, built-in names
141 * Fills ret with an answer and returns true if it handled the query.
142 *
d03c1b70 143 * Handles the following queries (and their ANY variants):
db50a7f4
PL
144 *
145 * - localhost. IN A
146 * - localhost. IN AAAA
147 * - 1.0.0.127.in-addr.arpa. IN PTR
148 * - 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
149 * - version.bind. CH TXT
150 * - version.pdns. CH TXT
151 * - id.server. CH TXT
db50a7f4 152 */
6dfff36f 153bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret)
db50a7f4
PL
154{
155 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."),
156 localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns.");
157
158 bool handled = false;
d03c1b70 159 vector<pair<QType::typeenum, string> > answers;
db50a7f4 160
d03c1b70
PL
161 if ((qname == arpa || qname == ip6_arpa) &&
162 qclass == QClass::IN) {
db50a7f4 163 handled = true;
d03c1b70
PL
164 if (qtype == QType::PTR || qtype == QType::ANY)
165 answers.push_back({QType::PTR, "localhost."});
db50a7f4
PL
166 }
167
d03c1b70
PL
168 if (qname == localhost &&
169 qclass == QClass::IN) {
db50a7f4 170 handled = true;
d03c1b70
PL
171 if (qtype == QType::A || qtype == QType::ANY)
172 answers.push_back({QType::A, "127.0.0.1"});
173 if (qtype == QType::AAAA || qtype == QType::ANY)
174 answers.push_back({QType::AAAA, "::1"});
db50a7f4
PL
175 }
176
d03c1b70
PL
177 if ((qname == versionbind || qname == idserver || qname == versionpdns) &&
178 qclass == QClass::CHAOS) {
db50a7f4 179 handled = true;
d03c1b70
PL
180 if (qtype == QType::TXT || qtype == QType::ANY) {
181 if(qname == versionbind || qname == versionpdns)
182 answers.push_back({QType::TXT, "\""+::arg()["version-string"]+"\""});
183 else
184 answers.push_back({QType::TXT, "\""+s_serverID+"\""});
185 }
31ad43ab
BH
186 }
187
d03c1b70 188 if (handled && !answers.empty()) {
a9af3782 189 ret.clear();
db50a7f4
PL
190 d_wasOutOfBand=true;
191
e325f20c 192 DNSRecord dr;
db50a7f4 193 dr.d_name = qname;
e693ff5a 194 dr.d_place = DNSResourceRecord::ANSWER;
db50a7f4
PL
195 dr.d_class = qclass;
196 dr.d_ttl = 86400;
d03c1b70
PL
197 for (const auto& ans : answers) {
198 dr.d_type = ans.first;
6177a176 199 dr.d_content = DNSRecordContent::mastermake(ans.first, qclass, ans.second);
d03c1b70
PL
200 ret.push_back(dr);
201 }
a9af3782 202 }
710af846 203
db50a7f4 204 return handled;
728485ca 205}
afbe2787 206
db50a7f4 207
ab5c053d 208//! This is the 'out of band resolver', in other words, the authoritative server
3337c2f7 209void SyncRes::AuthDomain::addSOA(std::vector<DNSRecord>& records) const
e93c956b 210{
3337c2f7
RG
211 SyncRes::AuthDomain::records_t::const_iterator ziter = d_records.find(boost::make_tuple(getName(), QType::SOA));
212 if (ziter != d_records.end()) {
213 DNSRecord dr = *ziter;
214 dr.d_place = DNSResourceRecord::AUTHORITY;
215 records.push_back(dr);
5605c067 216 }
3337c2f7
RG
217 else {
218 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
219 }
220}
5605c067 221
3337c2f7
RG
222int SyncRes::AuthDomain::getRecords(const DNSName& qname, uint16_t qtype, std::vector<DNSRecord>& records) const
223{
224 int result = RCode::NoError;
225 records.clear();
5605c067 226
3337c2f7
RG
227 // partial lookup
228 std::pair<records_t::const_iterator,records_t::const_iterator> range = d_records.equal_range(tie(qname));
229
230 SyncRes::AuthDomain::records_t::const_iterator ziter;
231 bool somedata = false;
232
233 for(ziter = range.first; ziter != range.second; ++ziter) {
234 somedata = true;
235
236 if(qtype == QType::ANY || ziter->d_type == qtype || ziter->d_type == QType::CNAME) {
237 // let rest of nameserver do the legwork on this one
238 records.push_back(*ziter);
239 }
240 else if (ziter->d_type == QType::NS && ziter->d_name.countLabels() > getName().countLabels()) {
241 // we hit a delegation point!
242 DNSRecord dr = *ziter;
39eb8051 243 dr.d_place=DNSResourceRecord::AUTHORITY;
3337c2f7 244 records.push_back(dr);
39eb8051 245 }
5605c067 246 }
3337c2f7
RG
247
248 if (!records.empty()) {
249 /* We have found an exact match, we're done */
250 // cerr<<qname<<": exact match in zone '"<<getName()<<"'"<<endl;
251 return result;
5605c067 252 }
3337c2f7
RG
253
254 if (somedata) {
255 /* We have records for that name, but not of the wanted qtype */
256 // cerr<<qname<<": found record in '"<<getName()<<"', but nothing of the right type, sending SOA"<<endl;
257 addSOA(records);
258
259 return result;
9e9844e2 260 }
5605c067 261
3337c2f7 262 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
c5c066bf 263 DNSName wcarddomain(qname);
3337c2f7
RG
264 while(wcarddomain != getName() && wcarddomain.chopOff()) {
265 // cerr<<qname<<": trying '*."<<wcarddomain<<"' in "<<getName()<<endl;
266 range = d_records.equal_range(boost::make_tuple(g_wildcarddnsname + wcarddomain));
267 if (range.first==range.second)
0d1e259a
BH
268 continue;
269
3337c2f7
RG
270 for(ziter = range.first; ziter != range.second; ++ziter) {
271 DNSRecord dr = *ziter;
0f05b02b 272 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
3337c2f7 273 if(dr.d_type == qtype || qtype == QType::ANY || dr.d_type == QType::CNAME) {
e325f20c 274 dr.d_name = qname;
3337c2f7
RG
275 dr.d_place = DNSResourceRecord::ANSWER;
276 records.push_back(dr);
0d1e259a
BH
277 }
278 }
3337c2f7
RG
279
280 if (records.empty()) {
281 addSOA(records);
282 }
283
284 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
285 return result;
0d1e259a
BH
286 }
287
3337c2f7 288 /* Nothing for this name, no wildcard, let's see if there is some NS */
c5c066bf 289 DNSName nsdomain(qname);
3337c2f7
RG
290 while (nsdomain.chopOff() && nsdomain != getName()) {
291 range = d_records.equal_range(boost::make_tuple(nsdomain,QType::NS));
292 if(range.first == range.second)
5605c067
BH
293 continue;
294
3337c2f7
RG
295 for(ziter = range.first; ziter != range.second; ++ziter) {
296 DNSRecord dr = *ziter;
297 dr.d_place = DNSResourceRecord::AUTHORITY;
298 records.push_back(dr);
5605c067
BH
299 }
300 }
3337c2f7
RG
301
302 if(records.empty()) {
303 // cerr<<qname<<": no NS match in zone '"<<getName()<<"' either, handing out SOA"<<endl;
304 addSOA(records);
305 result = RCode::NXDomain;
5605c067 306 }
5605c067 307
3337c2f7
RG
308 return result;
309}
310
311bool SyncRes::doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res) const
312{
313 res = domain.getRecords(qname, qtype.getCode(), ret);
9e9844e2 314 return true;
e93c956b
BH
315}
316
3337c2f7
RG
317bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int& res)
318{
319 string prefix;
320 if(doLog()) {
321 prefix=d_prefix;
322 prefix.append(depth, ' ');
323 }
324
325 DNSName authdomain(qname);
326 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
327 if(iter==t_sstorage.domainmap->end() || !iter->second.isAuth()) {
328 LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
329 return false;
330 }
331
332 LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
333 return doOOBResolve(iter->second, qname, qtype, ret, res);
334}
335
ff1872cf
BH
336void SyncRes::doEDNSDumpAndClose(int fd)
337{
338 FILE* fp=fdopen(fd, "w");
a82f68f0
RG
339 if (!fp) {
340 return;
341 }
ff1872cf 342 fprintf(fp,"IP Address\tMode\tMode last updated at\n");
a712cb56 343 for(const auto& eds : t_sstorage.ednsstatus) {
57769f13 344 fprintf(fp, "%s\t%d\t%s", eds.first.toString().c_str(), (int)eds.second.mode, ctime(&eds.second.modeSetAt));
ff1872cf 345 }
bb4bdbaf 346
ff1872cf
BH
347 fclose(fp);
348}
349
9065eb05
RG
350uint64_t SyncRes::doDumpNSSpeeds(int fd)
351{
352 FILE* fp=fdopen(dup(fd), "w");
353 if(!fp)
354 return 0;
355 fprintf(fp, "; nsspeed dump from thread follows\n;\n");
356 uint64_t count=0;
357
a712cb56 358 for(const auto& i : t_sstorage.nsSpeeds)
9065eb05
RG
359 {
360 count++;
361 fprintf(fp, "%s -> ", i.first.toString().c_str());
362 for(const auto& j : i.second.d_collection)
363 {
364 // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
365 fprintf(fp, "%s/%f ", j.first.toString().c_str(), j.second.peek());
366 }
367 fprintf(fp, "\n");
368 }
369 fclose(fp);
370 return count;
371}
372
9d534f2a 373/* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide
374 to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records
375 so that if there are RRSIGs for a name, we'll have them.
376
377 However, some hosts simply can't answer questions which ask for DNSSEC. This can manifest itself as:
378 * No answer
379 * FormErr
380 * Nonsense answer
381
382 The cause of "No answer" may be fragmentation, and it is tempting to probe if smaller answers would get through.
383 Another cause of "No answer" may simply be a network condition.
384 Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
385
386 Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
387 A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
388 clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
389 elsewhere. It may not have happened yet.
390
391 For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
392*/
393
69cbdef9 394int 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) const
81883dcc
BH
395{
396 /* what is your QUEST?
57769f13 397 the goal is to get as many remotes as possible on the highest level of EDNS support
81883dcc
BH
398 The levels are:
399
81883dcc 400 0) UNKNOWN Unknown state
57769f13 401 1) EDNS: Honors EDNS0
402 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
9d534f2a 403 3) NOEDNS: Generates FORMERR/NOTIMP on EDNS queries
81883dcc
BH
404
405 Everybody starts out assumed to be '0'.
57769f13 406 If '0', send out EDNS0
407 If you FORMERR us, go to '3',
408 If no EDNS in response, go to '2'
409 If '1', send out EDNS0
410 If FORMERR, downgrade to 3
411 If '2', keep on including EDNS0, see what happens
81883dcc 412 Same behaviour as 0
57769f13 413 If '3', send bare queries
81883dcc
BH
414 */
415
bb4bdbaf 416 SyncRes::EDNSStatus* ednsstatus;
a712cb56 417 ednsstatus = &t_sstorage.ednsstatus[ip]; // does this include port? YES
81883dcc 418
bb4bdbaf
BH
419 if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
420 *ednsstatus=SyncRes::EDNSStatus();
77499b05 421 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
81883dcc
BH
422 }
423
bb4bdbaf 424 SyncRes::EDNSStatus::EDNSMode& mode=ednsstatus->mode;
81883dcc 425 SyncRes::EDNSStatus::EDNSMode oldmode = mode;
fe61f5d8 426 int EDNSLevel = 0;
4898a348
RG
427 auto luaconfsLocal = g_luaconfs.getLocal();
428 ResolveContext ctx;
429#ifdef HAVE_PROTOBUF
430 ctx.d_initialRequestId = d_initialRequestId;
431#endif
81883dcc
BH
432
433 int ret;
ff1872cf 434 for(int tries = 0; tries < 3; ++tries) {
e325f20c 435 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
57769f13 436
9d534f2a 437 if(mode==EDNSStatus::NOEDNS) {
81883dcc 438 g_stats.noEdnsOutQueries++;
9d534f2a 439 EDNSLevel = 0; // level != mode
81883dcc 440 }
9d534f2a 441 else if(ednsMANDATORY || mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT)
442 EDNSLevel = 1;
30ee601a
RG
443
444 if (d_asyncResolve) {
445 ret = d_asyncResolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, luaconfsLocal->outgoingProtobufServer, res);
446 }
447 else {
448 ret=asyncresolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, luaconfsLocal->outgoingProtobufServer, res);
449 }
9d534f2a 450 if(ret < 0) {
451 return ret; // transport error, nothing to learn here
452 }
57769f13 453
9d534f2a 454 if(ret == 0) { // timeout, not doing anything with it now
81883dcc
BH
455 return ret;
456 }
57769f13 457 else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
458 if(res->d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp) {
2189085d 459 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
57769f13 460 mode = EDNSStatus::NOEDNS;
4957a608 461 continue;
81883dcc 462 }
81883dcc 463 else if(!res->d_haveEDNS) {
4957a608
BH
464 if(mode != EDNSStatus::EDNSIGNORANT) {
465 mode = EDNSStatus::EDNSIGNORANT;
2189085d 466 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 3"<<endl;
57769f13 467 }
81883dcc 468 }
57769f13 469 else {
470 mode = EDNSStatus::EDNSOK;
e325f20c 471 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
81883dcc 472 }
57769f13 473
81883dcc 474 }
12ce523e 475 if(oldmode != mode || !ednsstatus->modeSetAt)
bb4bdbaf 476 ednsstatus->modeSetAt=d_now.tv_sec;
e325f20c 477 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
81883dcc
BH
478 return ret;
479 }
480 return ret;
481}
482
b88526ce
PL
483/*! This function will check the cache and go out to the internet if the answer is not in cache
484 *
485 * \param qname The name we need an answer for
486 * \param qtype
487 * \param ret The vector of DNSRecords we need to fill with the answers
488 * \param depth The recursion depth we are in
489 * \param beenthere
490 * \return DNS RCODE or -1 (Error) or -2 (RPZ hit)
491 */
ad75fdbd 492int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state, SyncRes::zonesStates_t& cuts)
afbe2787 493{
ded77b10 494 string prefix;
77499b05 495 if(doLog()) {
ded77b10
BH
496 prefix=d_prefix;
497 prefix.append(depth, ' ');
498 }
b8470add 499
4d2be65d
RG
500 LOG(prefix<<qname<<": Wants "<< (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing, "<<(d_requireAuthData ? "" : "NO ")<<"auth data in query for "<<qtype.getName()<<endl);
501
502 state = Indeterminate;
710af846 503
7c3398aa
RG
504 if(s_maxdepth && depth > s_maxdepth)
505 throw ImmediateServFailException("More than "+std::to_string(s_maxdepth)+" (max-recursion-depth) levels of recursion needed while resolving "+qname.toLogString());
506
f4df5e89 507 int res=0;
b88526ce
PL
508
509 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
0b29b9c5 510 if(!(d_updatingRootNS && qtype.getCode()==QType::NS && qname.isRoot())) {
115d07ad 511 if(d_cacheonly) { // very limited OOB support
263f6a5a 512 LWResult lwr;
2189085d 513 LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
c5c066bf 514 DNSName authname(qname);
115d07ad 515 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
a712cb56 516 if(iter != t_sstorage.domainmap->end()) {
3337c2f7 517 if(iter->second.isAuth()) {
4957a608 518 ret.clear();
9fc36e90 519 d_wasOutOfBand = doOOBResolve(qname, qtype, ret, depth, res);
4957a608
BH
520 return res;
521 }
522 else {
3337c2f7 523 const vector<ComboAddress>& servers = iter->second.d_servers;
4957a608 524 const ComboAddress remoteIP = servers.front();
2189085d 525 LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
4957a608 526
6148fa97 527 boost::optional<Netmask> nm;
12ce523e 528 res=asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(), false, false, &d_now, nm, &lwr);
4957a608 529 // filter out the good stuff from lwr.result()
ab33a095
RG
530 if (res == 1) {
531 for(const auto& rec : lwr.d_records) {
532 if(rec.d_place == DNSResourceRecord::ANSWER)
533 ret.push_back(rec);
534 }
535 return 0;
536 }
537 else {
538 return RCode::ServFail;
4957a608 539 }
4957a608 540 }
115d07ad
BH
541 }
542 }
543
ad75fdbd 544 if(!d_skipCNAMECheck && doCNAMECacheCheck(qname,qtype,ret,depth,res,state, cuts)) // will reroute us if needed
c836dc19 545 return res;
710af846 546
4d2be65d 547 if(doCacheCheck(qname,qtype,ret,depth,res,state)) // we done
c836dc19
BH
548 return res;
549 }
afbe2787 550
115d07ad 551 if(d_cacheonly)
c836dc19 552 return 0;
728485ca 553
2189085d 554 LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
710af846 555
c5c066bf 556 DNSName subdomain(qname);
d8049162 557 if(qtype == QType::DS) subdomain.chopOff();
728485ca 558
fa1b87ff 559 NsSet nsset;
7305df82 560 bool flawedNSSet=false;
97df07f8 561
ad75fdbd 562 computeZoneCuts(cuts, qname, g_rootdnsname, depth);
70b3fe7a 563
97df07f8
PD
564 // the two retries allow getBestNSNamesFromCache&co to reprime the root
565 // hints, in case they ever go missing
bdf40704 566 for(int tries=0;tries<2 && nsset.empty();++tries) {
891fbf88 567 subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
bdf40704
BH
568 }
569
70b3fe7a
RG
570 state = getValidationStatus(cuts, subdomain);
571
4d2be65d
RG
572 LOG("Initial validation status for "<<qname<<" inherited from "<<subdomain<<" is "<<vStates[state]<<endl);
573
70b3fe7a 574 if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state, cuts)))
728485ca 575 return 0;
3ddb9247 576
2189085d 577 LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
b8470add
PL
578
579 if (res == -2)
580 return res;
581
20177d1d 582 return res<0 ? RCode::ServFail : res;
afbe2787
BH
583}
584
c2567ad1 585#if 0
a67dd0cf 586// for testing purposes
fdf05fd4
BH
587static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
588{
589 return !(a.sin4.sin_family < a.sin4.sin_family);
590}
c2567ad1 591#endif
fdf05fd4 592
21f0f88b 593/** This function explicitly goes out for A or AAAA addresses
996c89cc 594*/
7c3398aa 595vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere)
75b49099 596{
e325f20c 597 typedef vector<DNSRecord> res_t;
bfea0d0b 598 res_t res;
75b49099 599
996c89cc
BH
600 typedef vector<ComboAddress> ret_t;
601 ret_t ret;
75b49099 602
d96e88da 603 QType type;
24bb9b58
RG
604 bool oldRequireAuthData = d_requireAuthData;
605 d_requireAuthData = false;
92011b8f 606
607 for(int j=1; j<2+s_doIPv6; j++)
d96e88da 608 {
76c01aec 609 bool done=false;
76c01aec
PD
610 switch(j) {
611 case 0:
612 type = QType::ANY;
613 break;
614 case 1:
615 type = QType::A;
616 break;
617 case 2:
618 type = QType::AAAA;
619 break;
620 }
d96e88da 621
4d2be65d 622 vState newState = Indeterminate;
ad75fdbd
RG
623 zonesStates_t cuts;
624 if(!doResolve(qname, type, res,depth+1, beenthere, newState, cuts) && !res.empty()) { // this consults cache, OR goes out
d96e88da 625 for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
e325f20c 626 if(i->d_type == QType::A || i->d_type == QType::AAAA) {
627 if(auto rec = std::dynamic_pointer_cast<ARecordContent>(i->d_content))
628 ret.push_back(rec->getCA(53));
dd079764
RG
629 else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(i->d_content))
630 ret.push_back(aaaarec->getCA(53));
92011b8f 631 done=true;
d96e88da 632 }
42724edf 633 }
f4df5e89 634 }
710af846 635 if(done) {
60c9a54f 636 if(j==1 && s_doIPv6) { // we got an A record, see if we have some AAAA lying around
e325f20c 637 vector<DNSRecord> cset;
24bb9b58 638 if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), false, &cset, d_requestor) > 0) {
e325f20c 639 for(auto k=cset.cbegin();k!=cset.cend();++k) {
640 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
ba3c54cb
RG
641 if (auto drc = std::dynamic_pointer_cast<AAAARecordContent>(k->d_content)) {
642 ComboAddress ca=drc->getCA(53);
643 ret.push_back(ca);
644 }
60c9a54f 645 }
646 }
647 }
648 }
649 break;
650 }
bfea0d0b 651 }
710af846 652
24bb9b58
RG
653 d_requireAuthData = oldRequireAuthData;
654
996c89cc 655 if(ret.size() > 1) {
51e2144e 656 random_shuffle(ret.begin(), ret.end(), dns_random);
996c89cc 657
ae4d8cf1 658 // move 'best' address for this nameserver name up front
a712cb56 659 nsspeeds_t::iterator best = t_sstorage.nsSpeeds.find(qname);
996c89cc 660
a712cb56 661 if(best != t_sstorage.nsSpeeds.end())
710af846 662 for(ret_t::iterator i=ret.begin(); i != ret.end(); ++i) {
4957a608
BH
663 if(*i==best->second.d_best) { // got the fastest one
664 if(i!=ret.begin()) {
665 *i=*ret.begin();
666 *ret.begin()=best->second.d_best;
667 }
668 break;
669 }
996c89cc
BH
670 }
671 }
fdf05fd4 672
728485ca 673 return ret;
75b49099
BH
674}
675
7c3398aa 676void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere)
86c152f2 677{
c5c066bf
PD
678 string prefix;
679 DNSName subdomain(qname);
77499b05 680 if(doLog()) {
ded77b10
BH
681 prefix=d_prefix;
682 prefix.append(depth, ' ');
683 }
75b49099 684 bestns.clear();
2b1b4054 685 bool brokeloop;
75b49099 686 do {
2b1b4054 687 brokeloop=false;
2189085d 688 LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
e325f20c 689 vector<DNSRecord> ns;
7305df82 690 *flawedNSSet = false;
4d2be65d 691
2b984251 692 if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), false, &ns, d_requestor) > 0) {
e325f20c 693 for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
694 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
695 vector<DNSRecord> aset;
4957a608 696
e325f20c 697 const DNSRecord& dr=*k;
ba3c54cb
RG
698 auto nrr = getRR<NSRecordContent>(dr);
699 if(nrr && (!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
24bb9b58 700 false, doLog() ? &aset : nullptr, d_requestor) > 5)) {
e325f20c 701 bestns.push_back(dr);
2189085d
PL
702 LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<nrr->getNS()<<"'"<<endl);
703 LOG(prefix<<qname<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
4957a608 704 if(!aset.empty()) {
e325f20c 705 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
4957a608
BH
706 }
707 else {
77499b05 708 LOG(", not in cache / did not look at cache"<<endl);
4957a608
BH
709 }
710 }
711 else {
712 *flawedNSSet=true;
e325f20c 713 LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
4957a608
BH
714 }
715 }
afbe2787 716 }
4d2be65d 717
75b49099 718 if(!bestns.empty()) {
4957a608 719 GetBestNSAnswer answer;
891fbf88 720 answer.qname=qname;
721 answer.qtype=qtype.getCode();
e325f20c 722 for(const auto& dr : bestns)
ba3c54cb 723 answer.bestns.insert(make_pair(dr.d_name, getRR<NSRecordContent>(dr)->getNS()));
891fbf88 724
4957a608 725 if(beenthere.count(answer)) {
2b1b4054 726 brokeloop=true;
2189085d 727 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
e325f20c 728 ;
77499b05
BH
729 if(doLog())
730 for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
2b1b4054 731 bool neo = !(*j< answer || answer<*j);
2189085d 732 LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
77499b05 733 }
4957a608
BH
734 bestns.clear();
735 }
736 else {
6576051d 737 beenthere.insert(answer);
2189085d 738 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
4957a608
BH
739 return;
740 }
75b49099 741 }
afbe2787 742 }
2189085d 743 LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
4d2be65d 744
52683ca3 745 if(subdomain.isRoot() && !brokeloop) {
7836f7b4 746 // We lost the root NS records
3ddb9247 747 primeHints();
2189085d 748 LOG(prefix<<qname<<": reprimed the root"<<endl);
0b29b9c5
RG
749 /* let's prevent an infinite loop */
750 if (!d_updatingRootNS) {
751 getRootNS(d_now, d_asyncResolve);
752 }
6576051d 753 }
4d2be65d 754 } while(subdomain.chopOff());
75b49099
BH
755}
756
69cbdef9 757SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) const
5605c067
BH
758{
759 SyncRes::domainmap_t::const_iterator ret;
760 do {
a712cb56
RG
761 ret=t_sstorage.domainmap->find(*qname);
762 if(ret!=t_sstorage.domainmap->end())
5605c067 763 break;
c5c066bf 764 }while(qname->chopOff());
5605c067
BH
765 return ret;
766}
288f4aa9 767
7bf26383 768/** doesn't actually do the work, leaves that to getBestNSFromCache */
7c3398aa 769DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere)
75b49099 770{
c5c066bf
PD
771 DNSName subdomain(qname);
772 DNSName authdomain(qname);
3ddb9247 773
5605c067 774 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
a712cb56 775 if(iter!=t_sstorage.domainmap->end()) {
3337c2f7 776 if( iter->second.isAuth() )
fa1b87ff
PL
777 // this gets picked up in doResolveAt, the empty DNSName, combined with the
778 // empty vector means 'we are auth for this zone'
779 nsset.insert({DNSName(), {{}, false}});
2e5ae2b2 780 else {
fa1b87ff
PL
781 // Again, picked up in doResolveAt. An empty DNSName, combined with a
782 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
6dfff36f 783 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
3337c2f7 784 nsset.insert({DNSName(), {iter->second.d_servers, iter->second.shouldRecurse() }});
2e5ae2b2 785 }
5605c067
BH
786 return authdomain;
787 }
788
e325f20c 789 vector<DNSRecord> bestns;
891fbf88 790 getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
75b49099 791
e325f20c 792 for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) {
fa1b87ff
PL
793 // The actual resolver code will not even look at the ComboAddress or bool
794 nsset.insert({std::dynamic_pointer_cast<NSRecordContent>(k->d_content)->getNS(), {{}, false}});
e325f20c 795 if(k==bestns.cbegin())
796 subdomain=k->d_name;
86c152f2 797 }
75b49099 798 return subdomain;
afbe2787
BH
799}
800
ad75fdbd 801bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res, vState& state, SyncRes::zonesStates_t& cuts)
afbe2787 802{
ded77b10 803 string prefix;
77499b05 804 if(doLog()) {
710af846 805 prefix=d_prefix;
ded77b10
BH
806 prefix.append(depth, ' ');
807 }
36f5e3db 808
40de2910 809 if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
2189085d 810 LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
c6644fc5
BH
811 res=RCode::ServFail;
812 return true;
813 }
3ddb9247 814
2189085d 815 LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<qname<<"|CNAME"<<"'"<<endl);
e325f20c 816 vector<DNSRecord> cset;
1f77f479 817 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
2b984251
RG
818 vector<std::shared_ptr<DNSRecord>> authorityRecs;
819 if(t_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), d_requireAuthData, &cset, d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state) > 0) {
36c5ee42 820
e325f20c 821 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
822 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
4d2be65d 823 LOG(prefix<<qname<<": Found cache CNAME hit for '"<< qname << "|CNAME" <<"' to '"<<j->d_content->getZoneRepresentation()<<"', validation state is "<<vStates[state]<<endl);
e325f20c 824 DNSRecord dr=*j;
825 dr.d_ttl-=d_now.tv_sec;
826 ret.push_back(dr);
1f77f479 827
4d2be65d
RG
828 for(const auto& signature : signatures) {
829 DNSRecord sigdr;
830 sigdr.d_type=QType::RRSIG;
831 sigdr.d_name=qname;
832 sigdr.d_ttl=j->d_ttl - d_now.tv_sec;
833 sigdr.d_content=signature;
834 sigdr.d_place=DNSResourceRecord::ANSWER;
835 sigdr.d_class=QClass::IN;
836 ret.push_back(sigdr);
837 }
1f77f479 838
2b984251
RG
839 for(const auto& rec : authorityRecs) {
840 DNSRecord dr(*rec);
841 dr.d_ttl=j->d_ttl - d_now.tv_sec;
842 ret.push_back(dr);
843 }
844
f8e7daf8 845 if(qtype != QType::CNAME) { // perhaps they really wanted a CNAME!
4957a608 846 set<GetBestNSAnswer>beenthere;
4d2be65d
RG
847
848 vState cnameState = Indeterminate;
ad75fdbd 849 res=doResolve(std::dynamic_pointer_cast<CNAMERecordContent>(j->d_content)->getTarget(), qtype, ret, depth+1, beenthere, cnameState, cuts);
4d2be65d
RG
850 LOG("Updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
851 updateValidationState(state, cnameState);
4957a608
BH
852 }
853 else
854 res=0;
4d2be65d 855
4957a608 856 return true;
ac539791
BH
857 }
858 }
afbe2787 859 }
2189085d 860 LOG(prefix<<qname<<": No CNAME cache hit of '"<< qname << "|CNAME" <<"' found"<<endl);
75b49099
BH
861 return false;
862}
863
6909b8c5
PL
864/*!
865 * Convience function to push the records from records into ret with a new TTL
866 *
867 * \param records DNSRecords that need to go into ret
868 * \param ttl The new TTL for these records
869 * \param ret The vector of DNSRecords that should contian the records with the modified TTL
870 */
871static void addTTLModifiedRecords(const vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
39ce10b2
PL
872 for (const auto& rec : records) {
873 DNSRecord r(rec);
874 r.d_ttl = ttl;
875 ret.push_back(r);
876 }
877}
878
e325f20c 879
4d2be65d 880bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
75b49099 881{
fd8bc993 882 bool giveNegative=false;
710af846 883
be718669 884 string prefix;
77499b05 885 if(doLog()) {
ded77b10
BH
886 prefix=d_prefix;
887 prefix.append(depth, ' ');
888 }
afbe2787 889
30e9bd93 890 // 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 891 DNSName sqname(qname);
288f4aa9 892 QType sqt(qtype);
092f210a 893 uint32_t sttl=0;
2189085d 894 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
3ddb9247 895
64a8b6a1 896 DNSName authname(qname);
4d2be65d 897 vState cachedState;
129bb0c3
RG
898 bool wasForwardedOrAuth = false;
899 bool wasAuth = false;
900 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
a712cb56 901 if(iter != t_sstorage.domainmap->end()) {
129bb0c3
RG
902 wasForwardedOrAuth = true;
903 const vector<ComboAddress>& servers = iter->second.d_servers;
904 if(servers.empty()) {
905 wasAuth = true;
906 }
907 }
39ce10b2 908 NegCache::NegCacheEntry ne;
64a8b6a1 909
710af846 910 if(s_rootNXTrust &&
a712cb56 911 t_sstorage.negcache.getRootNXTrust(qname, d_now, ne) &&
39ce10b2
PL
912 ne.d_auth.isRoot() &&
913 !(wasForwardedOrAuth && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
914 sttl = ne.d_ttd - d_now.tv_sec;
915 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' & '"<<ne.d_name<<"' for another "<<sttl<<" seconds"<<endl);
3ddb9247 916 res = RCode::NXDomain;
39ce10b2 917 giveNegative = true;
4d2be65d 918 cachedState = ne.d_validationState;
01402d56 919 }
a712cb56 920 else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) &&
39ce10b2
PL
921 !(wasForwardedOrAuth && ne.d_auth != authname)) { // Only the authname nameserver can neg cache entries
922 res = 0;
923 sttl = ne.d_ttd - d_now.tv_sec;
924 giveNegative = true;
4d2be65d 925 cachedState = ne.d_validationState;
39ce10b2
PL
926 if(ne.d_qtype.getCode()) {
927 LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
928 res = RCode::NoError;
fd8bc993 929 }
39ce10b2
PL
930 else {
931 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
932 res = RCode::NXDomain;
933 }
934 if(d_doDNSSEC) {
935 addTTLModifiedRecords(ne.DNSSECRecords.records, sttl, ret);
936 addTTLModifiedRecords(ne.DNSSECRecords.signatures, sttl, ret);
937 }
938 }
939
940 if (giveNegative) {
941 // Transplant SOA to the returned packet
942 addTTLModifiedRecords(ne.authoritySOA.records, sttl, ret);
943 if(d_doDNSSEC)
944 addTTLModifiedRecords(ne.authoritySOA.signatures, sttl, ret);
4d2be65d
RG
945
946 LOG("Updating validation state with negative cache content for "<<qname<<" to "<<vStates[cachedState]<<endl);
947 state = cachedState;
39ce10b2 948 return true;
fd8bc993 949 }
39ce10b2 950
e325f20c 951 vector<DNSRecord> cset;
75b49099 952 bool found=false, expired=false;
57769f13 953 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
2b984251 954 vector<std::shared_ptr<DNSRecord>> authorityRecs;
57769f13 955 uint32_t ttl=0;
2b984251 956 if(t_RC->get(d_now.tv_sec, sqname, sqt, d_requireAuthData, &cset, d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState) > 0) {
2189085d 957 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
e325f20c 958 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
959 LOG(j->d_content->getZoneRepresentation());
960 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
961 DNSRecord dr=*j;
962 ttl = (dr.d_ttl-=d_now.tv_sec);
e325f20c 963 ret.push_back(dr);
964 LOG("[ttl="<<dr.d_ttl<<"] ");
4957a608 965 found=true;
ac539791 966 }
75b49099 967 else {
77499b05 968 LOG("[expired] ");
4957a608 969 expired=true;
75b49099 970 }
afbe2787 971 }
57769f13 972
973 for(const auto& signature : signatures) {
e325f20c 974 DNSRecord dr;
975 dr.d_type=QType::RRSIG;
976 dr.d_name=sqname;
977 dr.d_ttl=ttl;
978 dr.d_content=signature;
39ce10b2 979 dr.d_place = DNSResourceRecord::ANSWER;
4d2be65d 980 dr.d_class=QClass::IN;
e325f20c 981 ret.push_back(dr);
57769f13 982 }
2b984251
RG
983
984 for(const auto& rec : authorityRecs) {
985 DNSRecord dr(*rec);
986 dr.d_ttl=ttl;
987 ret.push_back(dr);
988 }
989
77499b05 990 LOG(endl);
f4df5e89 991 if(found && !expired) {
4d2be65d 992 if (!giveNegative)
4957a608 993 res=0;
129bb0c3 994 d_wasOutOfBand = wasAuth;
4d2be65d
RG
995 LOG("Updating validation state with cache content for "<<qname<<" to "<<vStates[cachedState]<<endl);
996 state = cachedState;
75b49099 997 return true;
f4df5e89 998 }
75b49099 999 else
2189085d 1000 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
afbe2787 1001 }
f4df5e89 1002
75b49099
BH
1003 return false;
1004}
afbe2787 1005
69cbdef9 1006bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
75b49099 1007{
6a1010f7 1008 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
afbe2787
BH
1009}
1010
d8d0bb8f 1011struct speedOrder
eefd15f9 1012{
3ddb9247
PD
1013 speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
1014 bool operator()(const DNSName &a, const DNSName &b) const
c3d9d009
BH
1015 {
1016 return d_speeds[a] < d_speeds[b];
c3d9d009 1017 }
3ddb9247 1018 map<DNSName, double>& d_speeds;
c3d9d009
BH
1019};
1020
fa1b87ff 1021inline vector<DNSName> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
afbe2787 1022{
e8b23f3b 1023 vector<DNSName> rnameservers;
5ea6f7de 1024 rnameservers.reserve(tnameservers.size());
e8b23f3b 1025 for(const auto& tns:tnameservers) {
88490c03 1026 rnameservers.push_back(tns.first);
21f0f88b 1027 }
e8b23f3b 1028 map<DNSName, double> speeds;
461df9d2 1029
e8b23f3b 1030 for(const auto& val: rnameservers) {
79b8cdcc 1031 double speed;
a712cb56 1032 speed=t_sstorage.nsSpeeds[val].get(&d_now);
21f0f88b 1033 speeds[val]=speed;
eefd15f9 1034 }
51e2144e 1035 random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
996c89cc
BH
1036 speedOrder so(speeds);
1037 stable_sort(rnameservers.begin(),rnameservers.end(), so);
710af846 1038
77499b05
BH
1039 if(doLog()) {
1040 LOG(prefix<<"Nameservers: ");
e325f20c 1041 for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
3ddb9247 1042 if(i!=rnameservers.begin()) {
77499b05
BH
1043 LOG(", ");
1044 if(!((i-rnameservers.begin())%3)) {
1045 LOG(endl<<prefix<<" ");
1046 }
d8d0bb8f 1047 }
34dcd30c 1048 LOG((i->empty() ? string("<empty>") : i->toString())<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
d8d0bb8f 1049 }
77499b05 1050 LOG(endl);
d8d0bb8f 1051 }
728485ca 1052 return rnameservers;
afbe2787
BH
1053}
1054
bf7e4a70
BH
1055static bool magicAddrMatch(const QType& query, const QType& answer)
1056{
1057 if(query.getCode() != QType::ADDR)
1058 return false;
1059 return answer.getCode() == QType::A || answer.getCode() == QType::AAAA;
1060}
7738a23f 1061
2b984251
RG
1062static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
1063
39ce10b2
PL
1064/* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1065 *
1066 * \param records The records to parse for the authority SOA and NSEC(3) records
1067 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1068 */
1069static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne) {
620db2c8 1070 for(const auto& rec : records) {
39ce10b2
PL
1071 if(rec.d_place != DNSResourceRecord::AUTHORITY)
1072 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1073 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1074 // records MUST be in the same section as the records they cover.
1075 // Hence, we ignore all records outside of the AUTHORITY section.
1076 continue;
1077
620db2c8 1078 if(rec.d_type == QType::RRSIG) {
39ce10b2
PL
1079 auto rrsig = getRR<RRSIGRecordContent>(rec);
1080 if(rrsig) {
1081 if(rrsig->d_type == QType::SOA) {
1082 ne.authoritySOA.signatures.push_back(rec);
1083 }
1084 if(nsecTypes.count(rrsig->d_type)) {
1085 ne.DNSSECRecords.signatures.push_back(rec);
1086 }
1087 }
1088 continue;
1089 }
1090 if(rec.d_type == QType::SOA) {
1091 ne.authoritySOA.records.push_back(rec);
1092 continue;
1093 }
1094 if(nsecTypes.count(rec.d_type)) {
1095 ne.DNSSECRecords.records.push_back(rec);
1096 continue;
620db2c8 1097 }
620db2c8 1098 }
620db2c8 1099}
1100
4d2be65d
RG
1101static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
1102{
1103 cspmap_t cspmap;
1104 for(const auto& rec : ne.DNSSECRecords.signatures) {
1105 if(rec.d_type == QType::RRSIG) {
1106 auto rrc = getRR<RRSIGRecordContent>(rec);
1107 if (rrc) {
1108 cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
1109 }
1110 }
1111 }
1112 for(const auto& rec : ne.DNSSECRecords.records) {
1113 cspmap[{rec.d_name, rec.d_type}].records.push_back(rec.d_content);
1114 }
1115 return cspmap;
1116}
1117
39ce10b2
PL
1118// TODO remove after processRecords is fixed!
1119// Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
620db2c8 1120static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1121{
39ce10b2
PL
1122 NegCache::NegCacheEntry ne;
1123 harvestNXRecords(records, ne);
1124 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
1125 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
1126 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
620db2c8 1127}
1128
69cbdef9 1129bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
26ca3513
RG
1130{
1131 if(d_wantsRPZ) {
1132 for (auto const &ns : nameservers) {
69cbdef9 1133 d_appliedPolicy = dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
26ca3513
RG
1134 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1135 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1136 return true;
1137 }
1138
1139 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1140 for (auto const &address : ns.second.first) {
69cbdef9 1141 d_appliedPolicy = dfe.getProcessingPolicy(address, d_discardedPolicies);
26ca3513
RG
1142 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1143 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1144 return true;
1145 }
1146 }
1147 }
1148 }
1149 return false;
1150}
1151
69cbdef9 1152bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
26ca3513
RG
1153{
1154 if (d_wantsRPZ) {
69cbdef9 1155 d_appliedPolicy = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies);
26ca3513
RG
1156 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
1157 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
1158 return true;
1159 }
1160 }
1161 return false;
1162}
1163
1164vector<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)
1165{
1166 vector<ComboAddress> result;
1167
1168 if(!tns->empty()) {
1169 LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
1170 result = getAddrs(*tns, depth+2, beenthere);
1171 pierceDontQuery=false;
1172 }
1173 else {
1174 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
1175
1176 result = nameservers[*tns].first;
1177 if(result.size() > 1) {
1178 LOG("s");
1179 }
1180 LOG(endl);
1181
1182 sendRDQuery = nameservers[*tns].second;
1183 pierceDontQuery=true;
1184 }
1185 return result;
1186}
1187
1188bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1189{
a712cb56 1190 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
26ca3513
RG
1191 LOG(prefix<<qname<<": server throttled "<<endl);
1192 s_throttledqueries++; d_throttledqueries++;
1193 return true;
1194 }
a712cb56 1195 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
6dfff36f 1196 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
26ca3513
RG
1197 s_throttledqueries++; d_throttledqueries++;
1198 return true;
1199 }
9065eb05 1200 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
26ca3513
RG
1201 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
1202 s_dontqueries++;
1203 return true;
1204 }
1205 return false;
1206}
1207
4d2be65d
RG
1208bool SyncRes::validationEnabled() const
1209{
8455425c 1210 return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
4d2be65d
RG
1211}
1212
1213uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const
26ca3513 1214{
4d2be65d
RG
1215 uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
1216 for(const auto& record : records)
1217 lowestTTD = min(lowestTTD, record.d_ttl);
1218
1219 if (validationEnabled() && !signatures.empty()) {
1220 /* if we are validating, we don't want to cache records after their signatures
1221 expires. */
1222 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
1223 lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
1224
1225 for(const auto& sig : signatures) {
1226 if (sig->d_siginception <= d_now.tv_sec && sig->d_sigexpire > d_now.tv_sec) {
1227 // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
1228 lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
1229 }
1230 }
1231 }
1232
1233 return lowestTTD;
1234}
1235
1236void SyncRes::updateValidationState(vState& state, const vState stateUpdate)
1237{
1238 LOG(d_prefix<<"validation state was "<<std::string(vStates[state])<<", state update is "<<std::string(vStates[stateUpdate])<<endl);
1239
895449a5
RG
1240 if (stateUpdate == TA) {
1241 state = Secure;
4d2be65d
RG
1242 }
1243 else if (stateUpdate == NTA) {
1244 state = Insecure;
1245 }
895449a5
RG
1246 else if (stateUpdate == Bogus) {
1247 state = Bogus;
1248 }
1249 else if (state == Indeterminate) {
1250 state = stateUpdate;
1251 }
4d2be65d
RG
1252 else if (stateUpdate == Insecure) {
1253 if (state != Bogus) {
1254 state = Insecure;
1255 }
1256 }
4d2be65d
RG
1257 LOG(d_prefix<<" validation state is now "<<std::string(vStates[state])<<endl);
1258}
1259
1260vState SyncRes::getTA(const DNSName& zone, dsmap_t& ds)
1261{
1262 auto luaLocal = g_luaconfs.getLocal();
1263
1264 if (luaLocal->dsAnchors.empty()) {
1265 /* We have no TA, everything is insecure */
1266 return Insecure;
1267 }
1268
1269 std::string reason;
1270 if (haveNegativeTrustAnchor(luaLocal->negAnchors, zone, reason)) {
1271 LOG("Got NTA for "<<zone<<endl);
1272 return NTA;
1273 }
1274
1275 if (getTrustAnchor(luaLocal->dsAnchors, zone, ds)) {
1276 LOG("Got TA for "<<zone<<endl);
895449a5 1277 return TA;
4d2be65d
RG
1278 }
1279
1280 if (zone.isRoot()) {
1281 /* No TA for the root */
1282 return Insecure;
1283 }
1284
1285 return Indeterminate;
1286}
1287
8455425c
RG
1288static size_t countSupportedDS(const dsmap_t& dsmap)
1289{
1290 size_t count = 0;
1291
1292 for (const auto& ds : dsmap) {
1293 if (isSupportedDS(ds)) {
1294 count++;
1295 }
1296 }
1297
1298 return count;
1299}
1300
ad75fdbd 1301vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsigned int depth, SyncRes::zonesStates_t& cuts)
4d2be65d
RG
1302{
1303 vState result = getTA(zone, ds);
1304
1305 if (result != Indeterminate || taOnly) {
895449a5 1306 if ((result == Secure || result == TA) && countSupportedDS(ds) == 0) {
8455425c
RG
1307 ds.clear();
1308 result = Insecure;
1309 }
1310
4d2be65d
RG
1311 return result;
1312 }
1313
1314 bool oldSkipCNAME = d_skipCNAMECheck;
4d2be65d
RG
1315 bool oldRequireAuthData = d_requireAuthData;
1316 d_skipCNAMECheck = true;
4d2be65d
RG
1317 d_requireAuthData = false;
1318
1319 std::set<GetBestNSAnswer> beenthere;
1320 std::vector<DNSRecord> dsrecords;
1321
1322 vState state = Indeterminate;
ad75fdbd 1323 int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state, cuts);
4d2be65d 1324 d_skipCNAMECheck = oldSkipCNAME;
4d2be65d
RG
1325 d_requireAuthData = oldRequireAuthData;
1326
1327 if (rcode == RCode::NoError) {
1328 if (state == Secure) {
1329 for (const auto& record : dsrecords) {
1330 if (record.d_type == QType::DS) {
1331 const auto dscontent = getRR<DSRecordContent>(record);
8455425c 1332 if (dscontent && isSupportedDS(*dscontent)) {
4d2be65d
RG
1333 ds.insert(*dscontent);
1334 }
1335 }
1336 }
4d2be65d 1337
b7f378d1
RG
1338 if (ds.empty()) {
1339 return Insecure;
1340 }
4d2be65d 1341 }
b7f378d1 1342
4d2be65d
RG
1343 return state;
1344 }
1345
1346 LOG("Returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1347 return Bogus;
1348}
1349
70b3fe7a
RG
1350vState SyncRes::getValidationStatus(const SyncRes::zonesStates_t& cuts, const DNSName& subdomain)
1351{
1352 vState result = Indeterminate;
1353
1354 if (!validationEnabled()) {
1355 return result;
1356 }
1357 DNSName name(subdomain);
1358 do {
1359 const auto& it = cuts.find(name);
1360 if (it != cuts.cend()) {
ad75fdbd 1361 LOG("Got status "<<vStates[it->second]<<" for name "<<subdomain<<" (from "<<name<<")"<<endl);
70b3fe7a
RG
1362 return it->second;
1363 }
1364 }
1365 while (name.chopOff());
1366
1367 return result;
1368}
1369
ad75fdbd 1370void SyncRes::computeZoneCuts(SyncRes::zonesStates_t& cuts, const DNSName& begin, const DNSName& end, unsigned int depth)
4d2be65d 1371{
ad75fdbd
RG
1372 if (cuts.count(begin) != 0) {
1373 return;
4d2be65d
RG
1374 }
1375
1376 dsmap_t ds;
ad75fdbd 1377 vState cutState = getDSRecords(end, ds, false, depth, cuts);
70b3fe7a
RG
1378 if (cutState == TA) {
1379 cutState = Secure;
1380 }
1381 else if (cutState == NTA) {
1382 cutState = Insecure;
1383 }
1384 cuts[end] = cutState;
1385
ad75fdbd
RG
1386 if (!validationEnabled()) {
1387 return;
70b3fe7a
RG
1388 }
1389
1390 if(!begin.isPartOf(end)) {
f24465e5 1391 throw PDNSException(end.toLogString() + " is not part of " + begin.toString());
70b3fe7a
RG
1392 }
1393
ad75fdbd
RG
1394 if (d_computingZoneCut) {
1395 return;
1396 }
1397
1398 LOG(__func__<<", from "<<begin.toString()<<" to "<<end.toString()<<endl);
1399
70b3fe7a
RG
1400 DNSName qname(end);
1401 std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
1402
ad75fdbd
RG
1403 bool oldSkipCNAME = d_skipCNAMECheck;
1404 bool oldRequireAuthData = d_requireAuthData;
1405 bool oldComputingZoneCut = d_computingZoneCut;
1406 d_skipCNAMECheck = true;
1407 d_requireAuthData = false;
1408 d_computingZoneCut = true;
1409
70b3fe7a
RG
1410 while(qname != begin) {
1411 bool foundCut = false;
1412 if (labelsToAdd.empty())
1413 break;
1414
1415 qname.prependRawLabel(labelsToAdd.back());
1416 labelsToAdd.pop_back();
f24465e5 1417 LOG("- Looking for a cut at "<<qname<<endl);
70b3fe7a 1418
70b3fe7a
RG
1419 std::set<GetBestNSAnswer> beenthere;
1420 std::vector<DNSRecord> nsrecords;
1421
1422 vState state = Indeterminate;
ad75fdbd
RG
1423 SyncRes::zonesStates_t tempCuts;
1424 int rcode = doResolve(qname, QType(QType::NS), nsrecords, depth + 1, beenthere, state, tempCuts);
70b3fe7a
RG
1425
1426 if (rcode == RCode::NoError && !nsrecords.empty()) {
1427 for (const auto& record : nsrecords) {
1428 if(record.d_type != QType::NS || record.d_name != qname)
1429 continue;
1430 foundCut = true;
1431 break;
1432 }
1433 if (foundCut) {
f24465e5 1434 LOG("- Found cut at "<<qname<<endl);
70b3fe7a 1435 dsmap_t ds;
ad75fdbd 1436 vState newState = getDSRecords(qname, ds, cutState == Insecure || cutState == Bogus, depth, cuts);
a69867f2
RG
1437 if (newState != Indeterminate) {
1438 cutState = newState;
1439 }
f24465e5 1440 LOG("New state is "<<vStates[cutState]<<endl);
70b3fe7a
RG
1441 if (cutState == TA) {
1442 cutState = Secure;
1443 }
1444 else if (cutState == NTA) {
1445 cutState = Insecure;
1446 }
1447 cuts[qname] = cutState;
1448 }
1449 }
1450 }
1451
ad75fdbd
RG
1452 d_skipCNAMECheck = oldSkipCNAME;
1453 d_requireAuthData = oldRequireAuthData;
1454 d_computingZoneCut = oldComputingZoneCut;
1455
f24465e5 1456 LOG("List of cuts from "<<begin<<" to "<<end<<endl);
70b3fe7a 1457 for (const auto& cut : cuts) {
f24465e5 1458 LOG(" - "<<cut.first<<": "<<vStates[cut.second]<<endl);
70b3fe7a 1459 }
4d2be65d
RG
1460}
1461
ad75fdbd 1462vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth, SyncRes::zonesStates_t& cuts)
4d2be65d
RG
1463{
1464 dsmap_t ds;
1465 if (!signatures.empty()) {
1466 DNSName signer = getSigner(signatures);
1467
1468 if (!signer.empty() && signer.isPartOf(zone)) {
ad75fdbd 1469 vState state = getDSRecords(signer, ds, false, depth, cuts);
b7f378d1 1470
895449a5
RG
1471 if (state == TA) {
1472 state = Secure;
1473 }
4d2be65d 1474 if (state != Secure) {
8455425c
RG
1475 if (state == NTA) {
1476 state = Insecure;
1477 }
4d2be65d
RG
1478 return state;
1479 }
1480 }
1481 }
1482
1483 skeyset_t tentativeKeys;
1484 std::vector<shared_ptr<DNSRecordContent> > toSign;
1485
1486 for (const auto& dnskey : dnskeys) {
1487 if (dnskey.d_type == QType::DNSKEY) {
1488 auto content = getRR<DNSKEYRecordContent>(dnskey);
1489 if (content) {
1490 tentativeKeys.insert(content);
1491 toSign.push_back(content);
1492 }
1493 }
1494 }
1495
1496 LOG("Trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
1497 skeyset_t validatedKeys;
1498 validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
1499
1500 LOG("We now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
1501
1502 if (validatedKeys.size() != tentativeKeys.size()) {
1503 LOG("Returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
1504 return Bogus;
1505 }
1506
1507 return Secure;
1508}
1509
ad75fdbd 1510vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth, SyncRes::zonesStates_t& cuts)
4d2be65d
RG
1511{
1512 std::vector<DNSRecord> records;
1513 std::set<GetBestNSAnswer> beenthere;
1514 LOG("Retrieving DNSKeys for "<<signer<<endl);
1515
1516 vState state = Indeterminate;
c7385ddb
RG
1517 /* following CNAME might lead to us to the wrong DNSKEY */
1518 bool oldSkipCNAME = d_skipCNAMECheck;
1519 d_skipCNAMECheck = true;
ad75fdbd 1520 int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state, cuts);
c7385ddb 1521 d_skipCNAMECheck = oldSkipCNAME;
4d2be65d
RG
1522
1523 if (rcode == RCode::NoError) {
1524 if (state == Secure) {
1525 for (const auto& key : records) {
1526 if (key.d_type == QType::DNSKEY) {
1527 auto content = getRR<DNSKEYRecordContent>(key);
1528 if (content) {
1529 keys.insert(content);
1530 }
1531 }
1532 }
1533 }
1534 LOG("Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<vStates[state]<<endl);
1535 return state;
1536 }
1537
1538 LOG("Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
1539 return Bogus;
1540}
1541
ad75fdbd 1542vState 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, SyncRes::zonesStates_t& cuts)
4d2be65d
RG
1543{
1544 skeyset_t keys;
1545 if (!signatures.empty()) {
1546 const DNSName signer = getSigner(signatures);
1547 if (!signer.empty() && name.isPartOf(signer)) {
15f44f1d
RG
1548 if (qtype == QType::DNSKEY && signer == qname) {
1549 /* we are already retrieving those keys, sorry */
1550 return Indeterminate;
1551 }
ad75fdbd 1552 vState state = getDNSKeys(signer, keys, depth, cuts);
4d2be65d
RG
1553 if (state != Secure) {
1554 return state;
1555 }
1556 }
1557 } else {
1558 LOG("Bogus!"<<endl);
1559 return Bogus;
1560 }
1561
1562 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
1563 for (const auto& record : records) {
1564 recordcontents.push_back(record.d_content);
1565 }
1566
1567 LOG("Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
1568 if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
1569 LOG("Secure!"<<endl);
1570 return Secure;
1571 }
1572
1573 LOG("Bogus!"<<endl);
1574 return Bogus;
1575}
1576
ad75fdbd 1577RCode::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, SyncRes::zonesStates_t& cuts, bool& needWildcardProof)
4d2be65d
RG
1578{
1579 struct CacheEntry
26ca3513
RG
1580 {
1581 vector<DNSRecord> records;
1582 vector<shared_ptr<RRSIGRecordContent>> signatures;
4d2be65d 1583 uint32_t signaturesTTL{std::numeric_limits<uint32_t>::max()};
26ca3513
RG
1584 };
1585 struct CacheKey
1586 {
1587 DNSName name;
1588 uint16_t type;
1589 DNSResourceRecord::Place place;
1590 bool operator<(const CacheKey& rhs) const {
1591 return tie(name, type) < tie(rhs.name, rhs.type);
1592 }
1593 };
4d2be65d 1594 typedef map<CacheKey, CacheEntry> tcache_t;
26ca3513
RG
1595 tcache_t tcache;
1596
4d2be65d
RG
1597 string prefix;
1598 if(doLog()) {
1599 prefix=d_prefix;
1600 prefix.append(depth, ' ');
1601 }
1602
2b984251 1603 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
26ca3513 1604 for(const auto& rec : lwr.d_records) {
2b984251
RG
1605 if(needWildcardProof) {
1606 if (nsecTypes.count(rec.d_type)) {
1607 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1608 }
1609 else if (rec.d_type == QType::RRSIG) {
1610 auto rrsig = getRR<RRSIGRecordContent>(rec);
1611 if (rrsig && nsecTypes.count(rrsig->d_type)) {
1612 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1613 }
1614 }
1615 }
26ca3513
RG
1616 if(rec.d_type == QType::RRSIG) {
1617 auto rrsig = getRR<RRSIGRecordContent>(rec);
1618 if (rrsig) {
2b984251
RG
1619 if (rec.d_name == qname && rrsig->d_labels < rec.d_name.countLabels()) {
1620 LOG(prefix<<qname<<": RRSIG indicates the name was expanded from a wildcard, we need a wildcard proof"<<endl);
1621 needWildcardProof = true;
1622 }
1623
26ca3513
RG
1624 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
1625 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
4d2be65d 1626 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
1627 }
1628 }
1629 }
1630
1631 // reap all answers from this packet that are acceptable
1632 for(auto& rec : lwr.d_records) {
1633 if(rec.d_type == QType::OPT) {
1634 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
1635 continue;
1636 }
1637 LOG(prefix<<qname<<": accept answer '"<<rec.d_name<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"|"<<rec.d_content->getZoneRepresentation()<<"' from '"<<auth<<"' nameservers? "<<(int)rec.d_place<<" ");
1638 if(rec.d_type == QType::ANY) {
1639 LOG("NO! - we don't accept 'ANY' data"<<endl);
1640 continue;
1641 }
1642
1643 if(rec.d_name.isPartOf(auth)) {
1644 if(rec.d_type == QType::RRSIG) {
1645 LOG("RRSIG - separate"<<endl);
1646 }
4d2be65d 1647 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
1648 LOG("NO! Is from delegation-only zone"<<endl);
1649 s_nodelegated++;
1650 return RCode::NXDomain;
1651 }
1652 else {
1653 bool haveLogged = false;
a712cb56 1654 if (!t_sstorage.domainmap->empty()) {
26ca3513
RG
1655 // Check if we are authoritative for a zone in this answer
1656 DNSName tmp_qname(rec.d_name);
1657 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
a712cb56 1658 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
26ca3513
RG
1659 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
1660 if (auth_domain_iter->first != auth) {
1661 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
1662 continue;
1663 } else {
1664 LOG("YES! - This answer was ");
6dfff36f 1665 if (!wasForwarded) {
26ca3513
RG
1666 LOG("retrieved from the local auth store.");
1667 } else {
1668 LOG("received from a server we forward to.");
1669 }
1670 haveLogged = true;
1671 LOG(endl);
1672 }
1673 }
1674 }
1675 if (!haveLogged) {
1676 LOG("YES!"<<endl);
1677 }
1678
1679 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
1680
1681 DNSRecord dr(rec);
26ca3513 1682 dr.d_ttl += d_now.tv_sec;
2b984251 1683 dr.d_place=DNSResourceRecord::ANSWER;
26ca3513
RG
1684 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
1685 }
1686 }
1687 else
1688 LOG("NO!"<<endl);
1689 }
1690
1691 // supplant
4d2be65d
RG
1692 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
1693 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)
1694 uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
26ca3513
RG
1695
1696 for(auto& record : i->second.records)
4d2be65d 1697 record.d_ttl = lowestTTD; // boom
26ca3513
RG
1698 }
1699
1700// cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
1701// cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
4d2be65d
RG
1702 }
1703
1704 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
4d2be65d 1705
26ca3513
RG
1706 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
1707 continue;
6dfff36f 1708
70b3fe7a
RG
1709// vState recordState = state;
1710 vState recordState = getValidationStatus(cuts, i->first.name);
f24465e5 1711 LOG("Got status "<<vStates[recordState]<<" for record "<<i->first.name<<endl);
70b3fe7a
RG
1712
1713 if (validationEnabled() && recordState == Secure) {
4d2be65d
RG
1714 if (lwr.d_aabit) {
1715 if (i->first.place != DNSResourceRecord::ADDITIONAL) {
1716 /* the additional entries can be insecure,
1717 like glue:
1718 "Glue address RRsets associated with delegations MUST NOT be signed"
1719 */
1720 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) {
88cb0fe0 1721 LOG("Validating DNSKEY for "<<i->first.name<<endl);
ad75fdbd 1722 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth, cuts);
4d2be65d
RG
1723 }
1724 else {
88cb0fe0 1725 LOG("Validating non-additional record for "<<i->first.name<<endl);
ad75fdbd 1726 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures, cuts);
4d2be65d
RG
1727 }
1728 }
1729 }
1730 else {
88cb0fe0
RG
1731 /* for non authoritative answer, we only care about the DS record (or lack of) */
1732 if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
1733 LOG("Validating DS record for "<<i->first.name<<endl);
ad75fdbd 1734 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures, cuts);
4d2be65d
RG
1735 }
1736 }
1737 updateValidationState(state, recordState);
1738 }
1739 else {
1740 if (validationEnabled()) {
1741 LOG("Skipping validation because the current state is "<<vStates[state]<<endl);
1742 }
1743 }
1744
2b984251 1745 t_RC->replace(d_now.tv_sec, i->first.name, QType(i->first.type), i->second.records, i->second.signatures, authorityRecs, lwr.d_aabit, i->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none, recordState);
6dfff36f 1746
26ca3513
RG
1747 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
1748 d_wasVariable=true;
1749 }
1750
1751 return RCode::NoError;
1752}
1753
860d5e8e 1754void SyncRes::getDenialValidationState(NegCache::NegCacheEntry& ne, vState& state, const dState expectedState, bool allowOptOut)
4d2be65d
RG
1755{
1756 ne.d_validationState = state;
1757
1758 if (state == Secure) {
1759 cspmap_t csp = harvestCSPFromNE(ne);
1760 dState res = getDenial(csp, ne.d_name, ne.d_qtype.getCode());
1761 if (res != expectedState) {
860d5e8e
RG
1762 if (res == OPTOUT && allowOptOut) {
1763 LOG("OPT-out denial found for "<<ne.d_name<<", retuning Insecure"<<endl);
1764 ne.d_validationState = Secure;
1765 updateValidationState(state, Insecure);
1766 return;
4d2be65d 1767 }
d377bb54
RG
1768 else if (res == INSECURE) {
1769 LOG("Insecure denial found for "<<ne.d_name<<", retuning Insecure"<<endl);
1770 ne.d_validationState = Insecure;
1771 }
4d2be65d
RG
1772 else {
1773 LOG("Invalid denial found for "<<ne.d_name<<", retuning Bogus"<<endl);
1774 ne.d_validationState = Bogus;
1775 }
1776 updateValidationState(state, ne.d_validationState);
1777 }
1778 }
1779}
1780
2b984251 1781bool 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, bool needWildcardProof)
26ca3513
RG
1782{
1783 bool done = false;
1784
1785 for(auto& rec : lwr.d_records) {
1786 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
1787 continue;
1788
1789 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
1790 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
1791 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
1792
1793 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
1794 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
1795 ret.push_back(rec);
1796 if(!wasVariable()) {
39ce10b2
PL
1797 NegCache::NegCacheEntry ne;
1798
39ce10b2
PL
1799 ne.d_ttd = d_now.tv_sec + rec.d_ttl;
1800 ne.d_name = qname;
1801 ne.d_qtype = QType(0); // this encodes 'whole record'
898856ca 1802 ne.d_auth = rec.d_name;
39ce10b2 1803 harvestNXRecords(lwr.d_records, ne);
860d5e8e 1804 getDenialValidationState(ne, state, NXDOMAIN, false);
a712cb56 1805 t_sstorage.negcache.add(ne);
07e3cfb6 1806 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
9a1e060b 1807 ne.d_name = ne.d_name.getLastLabel();
a712cb56 1808 t_sstorage.negcache.add(ne);
26ca3513
RG
1809 }
1810 }
1811
1812 negindic=true;
1813 }
4d2be65d 1814 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
26ca3513
RG
1815 ret.push_back(rec);
1816 if (auto content = getRR<CNAMERecordContent>(rec)) {
1817 newtarget=content->getTarget();
1818 }
1819 }
2b984251 1820 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER) {
26ca3513
RG
1821 if(rec.d_type != QType::RRSIG || rec.d_name == qname)
1822 ret.push_back(rec); // enjoy your DNSSEC
1823 }
2b984251
RG
1824 else if(needWildcardProof && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::AUTHORITY) {
1825 ret.push_back(rec); // enjoy your DNSSEC
1826 }
26ca3513
RG
1827 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
1828 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
1829 (
1830 rec.d_type==qtype.getCode() || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, QType(rec.d_type)) ) ) || sendRDQuery
1831 )
1832 )
1833 {
1834 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
1835
1836 done=true;
1837 ret.push_back(rec);
1838 }
4d2be65d 1839 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::NS && qname.isPartOf(rec.d_name)) {
26ca3513
RG
1840 if(moreSpecificThan(rec.d_name,auth)) {
1841 newauth=rec.d_name;
1842 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
1843 realreferral=true;
1844 }
1845 else {
1846 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
1847 }
1848 if (auto content = getRR<NSRecordContent>(rec)) {
1849 nsset.insert(content->getNS());
1850 }
1851 }
4d2be65d 1852 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
26ca3513 1853 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
26ca3513 1854 }
860d5e8e 1855 else if(realreferral && rec.d_place==DNSResourceRecord::AUTHORITY && (rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && newauth.isPartOf(auth)) {
4d2be65d
RG
1856 /* we might have received a denial of the DS, let's check */
1857 if (state == Secure) {
1858 NegCache::NegCacheEntry ne;
1859 ne.d_auth = auth;
1860 ne.d_ttd = d_now.tv_sec + rec.d_ttl;
860d5e8e
RG
1861 ne.d_name = newauth;
1862 ne.d_qtype = QType::DS;
4d2be65d
RG
1863 harvestNXRecords(lwr.d_records, ne);
1864 cspmap_t csp = harvestCSPFromNE(ne);
860d5e8e 1865 dState denialState = getDenial(csp, newauth, QType::DS);
d377bb54 1866 if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
860d5e8e 1867 ne.d_validationState = Secure;
4d2be65d 1868 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
812c3a69
RG
1869 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
1870 updateValidationState(state, Insecure);
4d2be65d
RG
1871 if(!wasVariable()) {
1872 t_sstorage.negcache.add(ne);
1873 }
4d2be65d
RG
1874 }
1875 }
1876 }
1877 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
1878 lwr.d_rcode==RCode::NoError && qname.isPartOf(rec.d_name)) {
26ca3513
RG
1879 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
1880
1881 if(!newtarget.empty()) {
1882 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
1883 }
1884 else {
1885 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
1886 ret.push_back(rec);
1887 if(!wasVariable()) {
39ce10b2
PL
1888 NegCache::NegCacheEntry ne;
1889 ne.d_auth = rec.d_name;
1890 ne.d_ttd = d_now.tv_sec + rec.d_ttl;
1891 ne.d_name = qname;
1892 ne.d_qtype = qtype;
1893 harvestNXRecords(lwr.d_records, ne);
860d5e8e 1894 getDenialValidationState(ne, state, NXQTYPE, qtype == QType::DS);
26ca3513 1895 if(qtype.getCode()) { // prevents us from blacking out a whole domain
a712cb56 1896 t_sstorage.negcache.add(ne);
26ca3513
RG
1897 }
1898 }
1899 negindic=true;
1900 }
1901 }
1902 }
1903
1904 return done;
1905}
1906
6dfff36f
RG
1907bool 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)
1908{
1909 int resolveret;
1910 s_outqueries++;
1911 d_outqueries++;
1912
1913 if(d_outqueries + d_throttledqueries > s_maxqperq) {
1914 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
1915 }
1916
1917 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
1918 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");
1919 }
1920
1921 if(doTCP) {
1922 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
1923 s_tcpoutqueries++;
1924 d_tcpoutqueries++;
1925 }
1926
1927 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
1928 LOG(prefix<<qname<<": query handled by Lua"<<endl);
1929 }
1930 else {
1931 ednsmask=getEDNSSubnetMask(d_requestor, qname, remoteIP);
1932 if(ednsmask) {
1933 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
1934 }
1935 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(),
1936 doTCP, sendRDQuery, &d_now, ednsmask, &lwr); // <- we go out on the wire!
1937 if(ednsmask) {
1938 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
1939 }
1940 }
1941
1942 /* preoutquery killed the query by setting dq.rcode to -3 */
1943 if(resolveret==-3) {
1944 throw ImmediateServFailException("Query killed by policy");
1945 }
1946
1947 d_totUsec += lwr.d_usec;
1948 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
1949
1950 if(resolveret != 1) {
1951 /* Error while resolving */
1952 if(resolveret == 0) {
1953 /* Time out */
1954
1955 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
1956 d_timeouts++;
1957 s_outgoingtimeouts++;
1958
1959 if(remoteIP.sin4.sin_family == AF_INET)
1960 s_outgoing4timeouts++;
1961 else
1962 s_outgoing6timeouts++;
1963 }
1964 else if(resolveret == -2) {
1965 /* OS resource limit reached */
1966 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
1967 g_stats.resourceLimits++;
1968 }
1969 else {
1970 /* -1 means server unreachable */
1971 s_unreachables++;
1972 d_unreachables++;
1973 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
1974 }
1975
1976 if(resolveret != -2) { // don't account for resource limits, they are our own fault
1977 t_sstorage.nsSpeeds[nsName].submit(remoteIP, 1000000, &d_now); // 1 sec
1978
1979 // code below makes sure we don't filter COM or the root
1980 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) {
1981 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
1982 // mark server as down
1983 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
1984 }
1985 else if (resolveret == -1) {
1986 // unreachable, 1 minute or 100 queries
1987 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
1988 }
1989 else {
1990 // timeout
1991 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
1992 }
1993 }
1994
1995 return false;
1996 }
1997
1998 /* we got an answer */
1999 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
2000 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
2001 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2002 return false;
2003 }
2004
2005 /* this server sent a valid answer, mark it backup up if it was down */
2006 if(s_serverdownmaxfails > 0) {
2007 t_sstorage.fails.clear(remoteIP);
2008 }
2009
2010 if(lwr.d_tcbit) {
2011 *truncated = true;
2012
2013 if (doTCP) {
2014 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
2015 /* let's treat that as a ServFail answer from this server */
2016 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2017 return false;
2018 }
2019
2020 return true;
2021 }
2022
2023 return true;
2024}
2025
ad75fdbd 2026bool 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, SyncRes::zonesStates_t& cuts)
6dfff36f
RG
2027{
2028 string prefix;
2029 if(doLog()) {
2030 prefix=d_prefix;
2031 prefix.append(depth, ' ');
2032 }
2033
2034 if(s_minimumTTL) {
2035 for(auto& rec : lwr.d_records) {
2036 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
2037 }
2038 }
2039
2b984251 2040 bool needWildcardProof = false;
15f44f1d 2041 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, cuts, needWildcardProof);
6dfff36f
RG
2042 if (*rcode != RCode::NoError) {
2043 return true;
2044 }
2045
2046 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
2047
2048 set<DNSName> nsset;
2049 bool realreferral=false, negindic=false;
2050 DNSName newauth;
2051 DNSName newtarget;
2052
2b984251 2053 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof);
6dfff36f
RG
2054
2055 if(done){
2056 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
2057 *rcode = RCode::NoError;
2058 return true;
2059 }
2060
2061 if(!newtarget.empty()) {
2062 if(newtarget == qname) {
2063 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
2064 *rcode = RCode::ServFail;
2065 return true;
2066 }
2067
2068 if(depth > 10) {
2069 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
2070 *rcode = RCode::ServFail;
2071 return true;
2072 }
2073
2074 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
2075
2076 set<GetBestNSAnswer> beenthere2;
4d2be65d 2077 vState cnameState = Indeterminate;
ad75fdbd 2078 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState, cuts);
4d2be65d
RG
2079 LOG("Updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
2080 updateValidationState(state, cnameState);
2081
6dfff36f
RG
2082 return true;
2083 }
2084
2085 if(lwr.d_rcode == RCode::NXDomain) {
2086 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
2087
2088 if(d_doDNSSEC)
2089 addNXNSECS(ret, lwr.d_records);
2090
2091 *rcode = RCode::NXDomain;
2092 return true;
2093 }
2094
2095 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
2096 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
2097
2098 if(d_doDNSSEC)
2099 addNXNSECS(ret, lwr.d_records);
2100
2101 *rcode = RCode::NoError;
2102 return true;
2103 }
2104
2105 if(realreferral) {
2106 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
6dfff36f
RG
2107
2108 nameservers.clear();
2109 for (auto const &nameserver : nsset) {
2110 if (d_wantsRPZ) {
2111 d_appliedPolicy = dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
2112 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2113 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
2114 *rcode = -2;
2115 return true;
2116 }
2117 }
2118 nameservers.insert({nameserver, {{}, false}});
2119 }
2120 LOG("looping to them"<<endl);
2121 *gotNewServers = true;
812c3a69 2122 auth=newauth;
4d2be65d 2123
6dfff36f
RG
2124 return false;
2125 }
2126
2127 return false;
2128}
2129
b8470add
PL
2130/** returns:
2131 * -1 in case of no results
2132 * -2 when a FilterEngine Policy was hit
2133 * rcode otherwise
2134 */
fa1b87ff 2135int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
e325f20c 2136 vector<DNSRecord>&ret,
ad75fdbd 2137 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state, SyncRes::zonesStates_t& cuts)
86c152f2 2138{
69cbdef9 2139 auto luaconfsLocal = g_luaconfs.getLocal();
ded77b10 2140 string prefix;
77499b05 2141 if(doLog()) {
ded77b10
BH
2142 prefix=d_prefix;
2143 prefix.append(depth, ' ');
2144 }
3ddb9247 2145
b8470add
PL
2146 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
2147
69cbdef9 2148 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
26ca3513 2149 return -2;
b8470add
PL
2150 }
2151
2152 LOG(endl);
afbe2787
BH
2153
2154 for(;;) { // we may get more specific nameservers
e8b23f3b 2155 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
3ddb9247 2156
26ca3513
RG
2157 for(auto tns=rnameservers.cbegin();;++tns) {
2158 if(tns==rnameservers.cend()) {
2189085d 2159 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
03c09afe 2160 if(!auth.isRoot() && flawedNSSet) {
2189085d 2161 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
88490c03 2162
49a699c4 2163 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
4957a608
BH
2164 g_stats.nsSetInvalidations++;
2165 }
2166 return -1;
afbe2787 2167 }
6dfff36f 2168
21f0f88b 2169 // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
26ca3513
RG
2170 if(qname == *tns && qtype.getCode()==QType::A && rnameservers.size() > (size_t)(1+1*s_doIPv6)) {
2171 LOG(prefix<<qname<<": Not using NS to resolve itself! ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
4957a608 2172 continue;
20177d1d 2173 }
5605c067 2174
996c89cc 2175 typedef vector<ComboAddress> remoteIPs_t;
5605c067 2176 remoteIPs_t remoteIPs;
bfea0d0b 2177 remoteIPs_t::const_iterator remoteIP;
1c21f389 2178 bool pierceDontQuery=false;
c1d73d94 2179 bool sendRDQuery=false;
376effcf 2180 boost::optional<Netmask> ednsmask;
263f6a5a 2181 LWResult lwr;
6dfff36f
RG
2182 const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty());
2183 int rcode = RCode::NoError;
2184 bool gotNewServers = false;
2185
2186 if(tns->empty() && !wasForwarded) {
2189085d 2187 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
4d2be65d 2188 state = Insecure;
9fc36e90 2189 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
4957a608
BH
2190 lwr.d_tcbit=false;
2191 lwr.d_aabit=true;
6dfff36f
RG
2192
2193 /* we have received an answer, are we done ? */
70b3fe7a 2194 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state, cuts);
6dfff36f
RG
2195 if (done) {
2196 return rcode;
2197 }
2198 if (gotNewServers) {
2199 break;
2200 }
5605c067
BH
2201 }
2202 else {
6dfff36f 2203 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
26ca3513 2204 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet);
4957a608
BH
2205
2206 if(remoteIPs.empty()) {
2189085d 2207 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
4957a608
BH
2208 flawedNSSet=true;
2209 continue;
2210 }
2211 else {
b8470add 2212 bool hitPolicy{false};
2189085d 2213 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
26ca3513
RG
2214 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2215 if(remoteIP != remoteIPs.cbegin()) {
77499b05
BH
2216 LOG(", ");
2217 }
2218 LOG(remoteIP->toString());
69cbdef9 2219 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
26ca3513 2220 hitPolicy = true;
b8470add 2221 }
4957a608 2222 }
77499b05 2223 LOG(endl);
b8470add
PL
2224 if (hitPolicy) //implies d_wantsRPZ
2225 return -2;
4957a608
BH
2226 }
2227
26ca3513 2228 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2189085d 2229 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
6dfff36f 2230
26ca3513 2231 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
4957a608
BH
2232 continue;
2233 }
9de3e034 2234
6dfff36f
RG
2235 bool truncated = false;
2236 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2237 *tns, *remoteIP, false, &truncated);
2238 if (gotAnswer && truncated ) {
2239 /* retry, over TCP this time */
2240 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2241 *tns, *remoteIP, true, &truncated);
2242 }
710af846 2243
6dfff36f
RG
2244 if (!gotAnswer) {
2245 continue;
2246 }
352b4183 2247
6dfff36f 2248 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 2249
6dfff36f
RG
2250 /* // for you IPv6 fanatics :-)
2251 if(remoteIP->sin4.sin_family==AF_INET6)
2252 lwr.d_usec/=3;
2253 */
2254 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
710af846 2255
6dfff36f 2256 t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
628e2c7b 2257
6dfff36f 2258 /* we have received an answer, are we done ? */
70b3fe7a 2259 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state, cuts);
6dfff36f
RG
2260 if (done) {
2261 return rcode;
4957a608 2262 }
6dfff36f
RG
2263 if (gotNewServers) {
2264 break;
4957a608 2265 }
6dfff36f
RG
2266 /* was lame */
2267 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
4957a608 2268 }
aadceba8 2269
6dfff36f
RG
2270 if (gotNewServers) {
2271 break;
4957a608 2272 }
620db2c8 2273
6dfff36f
RG
2274 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
2275 continue;
620db2c8 2276
86c152f2
BH
2277 }
2278 }
86c152f2 2279 }
ac539791 2280 return -1;
86c152f2
BH
2281}
2282
e9f9b8ec
RG
2283boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem)
2284{
2285 boost::optional<Netmask> result;
2286 ComboAddress trunc;
2287 uint8_t bits;
2288 if(d_incomingECSFound) {
2289 if (d_incomingECS->source.getBits() == 0) {
2290 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0 */
2291 return result;
2292 }
2293 trunc = d_incomingECS->source.getMaskedNetwork();
2294 bits = d_incomingECS->source.getBits();
2295 }
2296 else if(!local.isIPv4() || local.sin4.sin_addr.s_addr) { // detect unset 'requestor'
2297 trunc = local;
2298 bits = local.isIPv4() ? 32 : 128;
2299 }
2300 else {
2301 /* nothing usable */
2302 return result;
2303 }
2304
9065eb05 2305 if(s_ednsdomains.check(dn) || s_ednssubnets.match(rem)) {
e9f9b8ec
RG
2306 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
2307 trunc.truncate(bits);
2308 return boost::optional<Netmask>(Netmask(trunc, bits));
2309 }
2310
2311 return result;
2312}
bd53ea9d 2313
9065eb05
RG
2314void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
2315{
2316 vector<string> parts;
2317 stringtok(parts, wlist, ",; ");
2318 for(const auto& a : parts) {
2319 try {
2320 s_ednssubnets.addMask(Netmask(a));
2321 }
2322 catch(...) {
2323 s_ednsdomains.add(DNSName(a));
2324 }
2325 }
2326}
2327
8ce79a22 2328// used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
a3e7b735 2329int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
bd53ea9d
PD
2330{
2331 struct timeval now;
2332 gettimeofday(&now, 0);
710af846 2333
bd53ea9d 2334 SyncRes sr(now);
a3e7b735 2335 int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
e325f20c 2336
bd53ea9d
PD
2337 return res;
2338}
30ee601a 2339
30ee601a
RG
2340int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
2341 SyncRes sr(now);
2342 sr.setDoEDNS0(true);
0b29b9c5 2343 sr.setUpdatingRootNS();
30ee601a
RG
2344 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
2345 sr.setAsyncCallback(asyncCallback);
2346
2347 vector<DNSRecord> ret;
2348 int res=-1;
2349 try {
2350 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
2351 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
4d2be65d 2352 auto state = sr.getValidationState();
30ee601a
RG
2353 if (state == Bogus)
2354 throw PDNSException("Got Bogus validation result for .|NS");
2355 }
2356 return res;
2357 }
c78ceb39 2358 catch(const PDNSException& e) {
30ee601a
RG
2359 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2360 }
c78ceb39
RG
2361 catch(const ImmediateServFailException& e) {
2362 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
2363 }
2364 catch(const std::exception& e) {
30ee601a
RG
2365 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
2366 }
c78ceb39 2367 catch(...) {
30ee601a
RG
2368 L<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
2369 }
c78ceb39 2370
30ee601a
RG
2371 if(!res) {
2372 L<<Logger::Notice<<"Refreshed . records"<<endl;
2373 }
2374 else
2375 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
c78ceb39 2376
30ee601a
RG
2377 return res;
2378}