]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/tcpreceiver.cc
Merge pull request #8385 from omoerbeek/more-strict-flags
[thirdparty/pdns.git] / pdns / tcpreceiver.cc
1 /*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002-2012 PowerDNS.COM BV
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
8
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <boost/algorithm/string.hpp>
26 #include "auth-packetcache.hh"
27 #include "utility.hh"
28 #include "threadname.hh"
29 #include "dnssecinfra.hh"
30 #include "dnsseckeeper.hh"
31 #include <cstdio>
32 #include "base32.hh"
33 #include <cstring>
34 #include <cstdlib>
35 #include <sys/types.h>
36 #include <netinet/tcp.h>
37 #include <iostream>
38 #include <string>
39 #include "tcpreceiver.hh"
40 #include "sstuff.hh"
41
42 #include <errno.h>
43 #include <signal.h>
44 #include "base64.hh"
45 #include "ueberbackend.hh"
46 #include "dnspacket.hh"
47 #include "nameserver.hh"
48 #include "distributor.hh"
49 #include "lock.hh"
50 #include "logger.hh"
51 #include "arguments.hh"
52
53 #include "common_startup.hh"
54 #include "packethandler.hh"
55 #include "statbag.hh"
56 #include "resolver.hh"
57 #include "communicator.hh"
58 #include "namespaces.hh"
59 #include "signingpipe.hh"
60 #include "stubresolver.hh"
61 extern AuthPacketCache PC;
62 extern StatBag S;
63
64 /**
65 \file tcpreceiver.cc
66 \brief This file implements the tcpreceiver that receives and answers questions over TCP/IP
67 */
68
69 pthread_mutex_t TCPNameserver::s_plock = PTHREAD_MUTEX_INITIALIZER;
70 std::unique_ptr<Semaphore> TCPNameserver::d_connectionroom_sem{nullptr};
71 std::unique_ptr<PacketHandler> TCPNameserver::s_P{nullptr};
72 unsigned int TCPNameserver::d_maxTCPConnections = 0;
73 NetmaskGroup TCPNameserver::d_ng;
74 size_t TCPNameserver::d_maxTransactionsPerConn;
75 size_t TCPNameserver::d_maxConnectionsPerClient;
76 unsigned int TCPNameserver::d_idleTimeout;
77 unsigned int TCPNameserver::d_maxConnectionDuration;
78 std::mutex TCPNameserver::s_clientsCountMutex;
79 std::map<ComboAddress,size_t,ComboAddress::addressOnlyLessThan> TCPNameserver::s_clientsCount;
80
81 void TCPNameserver::go()
82 {
83 g_log<<Logger::Error<<"Creating backend connection for TCP"<<endl;
84 s_P.reset();
85 try {
86 s_P=make_unique<PacketHandler>();
87 }
88 catch(PDNSException &ae) {
89 g_log<<Logger::Error<<"TCP server is unable to launch backends - will try again when questions come in: "<<ae.reason<<endl;
90 }
91 pthread_create(&d_tid, 0, launcher, static_cast<void *>(this));
92 }
93
94 void *TCPNameserver::launcher(void *data)
95 {
96 static_cast<TCPNameserver *>(data)->thread();
97 return 0;
98 }
99
100 // throws PDNSException if things didn't go according to plan, returns 0 if really 0 bytes were read
101 static int readnWithTimeout(int fd, void* buffer, unsigned int n, unsigned int idleTimeout, bool throwOnEOF=true, unsigned int totalTimeout=0)
102 {
103 unsigned int bytes=n;
104 char *ptr = (char*)buffer;
105 int ret;
106 time_t start = 0;
107 unsigned int remainingTotal = totalTimeout;
108 if (totalTimeout) {
109 start = time(NULL);
110 }
111 while(bytes) {
112 ret=read(fd, ptr, bytes);
113 if(ret < 0) {
114 if(errno==EAGAIN) {
115 ret=waitForData(fd, (totalTimeout == 0 || idleTimeout <= remainingTotal) ? idleTimeout : remainingTotal);
116 if(ret < 0)
117 throw NetworkError("Waiting for data read");
118 if(!ret)
119 throw NetworkError("Timeout reading data");
120 continue;
121 }
122 else
123 throw NetworkError("Reading data: "+stringerror());
124 }
125 if(!ret) {
126 if(!throwOnEOF && n == bytes)
127 return 0;
128 else
129 throw NetworkError("Did not fulfill read from TCP due to EOF");
130 }
131
132 ptr += ret;
133 bytes -= ret;
134 if (totalTimeout) {
135 time_t now = time(NULL);
136 unsigned int elapsed = now - start;
137 if (elapsed >= remainingTotal) {
138 throw NetworkError("Timeout while reading data");
139 }
140 start = now;
141 remainingTotal -= elapsed;
142 }
143 }
144 return n;
145 }
146
147 // ditto
148 static void writenWithTimeout(int fd, const void *buffer, unsigned int n, unsigned int idleTimeout)
149 {
150 unsigned int bytes=n;
151 const char *ptr = (char*)buffer;
152 int ret;
153 while(bytes) {
154 ret=write(fd, ptr, bytes);
155 if(ret < 0) {
156 if(errno==EAGAIN) {
157 ret=waitForRWData(fd, false, idleTimeout, 0);
158 if(ret < 0)
159 throw NetworkError("Waiting for data write");
160 if(!ret)
161 throw NetworkError("Timeout writing data");
162 continue;
163 }
164 else
165 throw NetworkError("Writing data: "+stringerror());
166 }
167 if(!ret) {
168 throw NetworkError("Did not fulfill TCP write due to EOF");
169 }
170
171 ptr += ret;
172 bytes -= ret;
173 }
174 }
175
176 void connectWithTimeout(int fd, struct sockaddr* remote, size_t socklen)
177 {
178 int err;
179 Utility::socklen_t len=sizeof(err);
180
181 if((err=connect(fd, remote, socklen))<0 && errno!=EINPROGRESS)
182 throw NetworkError("connect: "+stringerror());
183
184 if(!err)
185 goto done;
186
187 err=waitForRWData(fd, false, 5, 0);
188 if(err == 0)
189 throw NetworkError("Timeout connecting to remote");
190 if(err < 0)
191 throw NetworkError("Error connecting to remote");
192
193 if(getsockopt(fd, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0)
194 throw NetworkError("Error connecting to remote: "+stringerror()); // Solaris
195
196 if(err)
197 throw NetworkError("Error connecting to remote: "+string(strerror(err)));
198
199 done:
200 ;
201 }
202
203 void TCPNameserver::sendPacket(std::unique_ptr<DNSPacket>& p, int outsock)
204 {
205 g_rs.submitResponse(*p, false);
206
207 uint16_t len=htons(p->getString().length());
208 string buffer((const char*)&len, 2);
209 buffer.append(p->getString());
210 writenWithTimeout(outsock, buffer.c_str(), buffer.length(), d_idleTimeout);
211 }
212
213
214 void TCPNameserver::getQuestion(int fd, char *mesg, int pktlen, const ComboAddress &remote, unsigned int totalTime)
215 try
216 {
217 readnWithTimeout(fd, mesg, pktlen, d_idleTimeout, true, totalTime);
218 }
219 catch(NetworkError& ae) {
220 throw NetworkError("Error reading DNS data from TCP client "+remote.toString()+": "+ae.what());
221 }
222
223 static void incTCPAnswerCount(const ComboAddress& remote)
224 {
225 S.inc("tcp-answers");
226 if(remote.sin4.sin_family == AF_INET6)
227 S.inc("tcp6-answers");
228 else
229 S.inc("tcp4-answers");
230 }
231
232 static bool maxConnectionDurationReached(unsigned int maxConnectionDuration, time_t start, unsigned int& remainingTime)
233 {
234 if (maxConnectionDuration) {
235 time_t elapsed = time(NULL) - start;
236 if (elapsed >= maxConnectionDuration) {
237 return true;
238 }
239 remainingTime = maxConnectionDuration - elapsed;
240 }
241 return false;
242 }
243
244 void TCPNameserver::decrementClientCount(const ComboAddress& remote)
245 {
246 if (d_maxConnectionsPerClient) {
247 std::lock_guard<std::mutex> lock(s_clientsCountMutex);
248 s_clientsCount[remote]--;
249 if (s_clientsCount[remote] == 0) {
250 s_clientsCount.erase(remote);
251 }
252 }
253 }
254
255 void *TCPNameserver::doConnection(void *data)
256 {
257 setThreadName("pdns/tcpConnect");
258 std::unique_ptr<DNSPacket> packet;
259 // Fix gcc-4.0 error (on AMD64)
260 int fd=(int)(long)data; // gotta love C (generates a harmless warning on opteron)
261 ComboAddress remote;
262 socklen_t remotelen=sizeof(remote);
263 size_t transactions = 0;
264 time_t start = 0;
265 if (d_maxConnectionDuration) {
266 start = time(NULL);
267 }
268
269 pthread_detach(pthread_self());
270 if(getpeername(fd, (struct sockaddr *)&remote, &remotelen) < 0) {
271 g_log<<Logger::Warning<<"Received question from socket which had no remote address, dropping ("<<stringerror()<<")"<<endl;
272 d_connectionroom_sem->post();
273 try {
274 closesocket(fd);
275 }
276 catch(const PDNSException& e) {
277 g_log<<Logger::Error<<"Error closing TCP socket: "<<e.reason<<endl;
278 }
279 return 0;
280 }
281
282 setNonBlocking(fd);
283 try {
284 int mesgsize=65535;
285 scoped_array<char> mesg(new char[mesgsize]);
286
287 DLOG(g_log<<"TCP Connection accepted on fd "<<fd<<endl);
288 bool logDNSQueries= ::arg().mustDo("log-dns-queries");
289 for(;;) {
290 unsigned int remainingTime = 0;
291 transactions++;
292 if (d_maxTransactionsPerConn && transactions > d_maxTransactionsPerConn) {
293 g_log << Logger::Notice<<"TCP Remote "<< remote <<" exceeded the number of transactions per connection, dropping.";
294 break;
295 }
296 if (maxConnectionDurationReached(d_maxConnectionDuration, start, remainingTime)) {
297 g_log << Logger::Notice<<"TCP Remote "<< remote <<" exceeded the maximum TCP connection duration, dropping.";
298 break;
299 }
300
301 uint16_t pktlen;
302 if(!readnWithTimeout(fd, &pktlen, 2, d_idleTimeout, false, remainingTime))
303 break;
304 else
305 pktlen=ntohs(pktlen);
306
307 // this check will always be false *if* no one touches
308 // the mesg array. pktlen can be maximum of 65535 as
309 // it is 2 byte unsigned variable. In getQuestion, we
310 // write to 0 up to pktlen-1 so 65535 is just right.
311
312 // do not remove this check as it will catch if someone
313 // decreases the mesg buffer size for some reason.
314 if(pktlen > mesgsize) {
315 g_log<<Logger::Warning<<"Received an overly large question from "<<remote.toString()<<", dropping"<<endl;
316 break;
317 }
318
319 if (maxConnectionDurationReached(d_maxConnectionDuration, start, remainingTime)) {
320 g_log << Logger::Notice<<"TCP Remote "<< remote <<" exceeded the maximum TCP connection duration, dropping.";
321 break;
322 }
323
324 getQuestion(fd, mesg.get(), pktlen, remote, remainingTime);
325 S.inc("tcp-queries");
326 if(remote.sin4.sin_family == AF_INET6)
327 S.inc("tcp6-queries");
328 else
329 S.inc("tcp4-queries");
330
331 packet=make_unique<DNSPacket>(true);
332 packet->setRemote(&remote);
333 packet->d_tcp=true;
334 packet->setSocket(fd);
335 if(packet->parse(mesg.get(), pktlen)<0)
336 break;
337
338 if(packet->qtype.getCode()==QType::AXFR) {
339 if(doAXFR(packet->qdomain, packet, fd))
340 incTCPAnswerCount(remote);
341 continue;
342 }
343
344 if(packet->qtype.getCode()==QType::IXFR) {
345 if(doIXFR(packet, fd))
346 incTCPAnswerCount(remote);
347 continue;
348 }
349
350 std::unique_ptr<DNSPacket> reply;
351 auto cached = make_unique<DNSPacket>(false);
352 if(logDNSQueries) {
353 string remote_text;
354 if(packet->hasEDNSSubnet())
355 remote_text = packet->getRemote().toString() + "<-" + packet->getRealRemote().toString();
356 else
357 remote_text = packet->getRemote().toString();
358 g_log << Logger::Notice<<"TCP Remote "<< remote_text <<" wants '" << packet->qdomain<<"|"<<packet->qtype.getName() <<
359 "', do = " <<packet->d_dnssecOk <<", bufsize = "<< packet->getMaxReplyLen()<<": ";
360 }
361
362 if(PC.enabled()) {
363 if(packet->couldBeCached() && PC.get(*packet, *cached)) { // short circuit - does the PacketCache recognize this question?
364 if(logDNSQueries)
365 g_log<<"packetcache HIT"<<endl;
366 cached->setRemote(&packet->d_remote);
367 cached->d.id=packet->d.id;
368 cached->d.rd=packet->d.rd; // copy in recursion desired bit
369 cached->commitD(); // commit d to the packet inlined
370
371 sendPacket(cached, fd); // presigned, don't do it again
372 continue;
373 }
374 if(logDNSQueries)
375 g_log<<"packetcache MISS"<<endl;
376 }
377 {
378 Lock l(&s_plock);
379 if(!s_P) {
380 g_log<<Logger::Error<<"TCP server is without backend connections, launching"<<endl;
381 s_P=make_unique<PacketHandler>();
382 }
383
384 reply= s_P->doQuestion(*packet); // we really need to ask the backend :-)
385 }
386
387 if(!reply) // unable to write an answer?
388 break;
389
390 sendPacket(reply, fd);
391 }
392 }
393 catch(PDNSException &ae) {
394 Lock l(&s_plock);
395 s_P.reset(); // on next call, backend will be recycled
396 g_log<<Logger::Error<<"TCP nameserver had error, cycling backend: "<<ae.reason<<endl;
397 }
398 catch(NetworkError &e) {
399 g_log<<Logger::Info<<"TCP Connection Thread died because of network error: "<<e.what()<<endl;
400 }
401
402 catch(std::exception &e) {
403 g_log<<Logger::Error<<"TCP Connection Thread died because of STL error: "<<e.what()<<endl;
404 }
405 catch( ... )
406 {
407 g_log << Logger::Error << "TCP Connection Thread caught unknown exception." << endl;
408 }
409 d_connectionroom_sem->post();
410
411 try {
412 closesocket(fd);
413 }
414 catch(const PDNSException& e) {
415 g_log<<Logger::Error<<"Error closing TCP socket: "<<e.reason<<endl;
416 }
417 decrementClientCount(remote);
418
419 return 0;
420 }
421
422
423 // call this method with s_plock held!
424 bool TCPNameserver::canDoAXFR(std::unique_ptr<DNSPacket>& q)
425 {
426 if(::arg().mustDo("disable-axfr"))
427 return false;
428
429 if(q->d_havetsig) { // if you have one, it must be good
430 TSIGRecordContent trc;
431 DNSName keyname;
432 string secret;
433 if(!q->checkForCorrectTSIG(s_P->getBackend(), &keyname, &secret, &trc)) {
434 return false;
435 } else {
436 getTSIGHashEnum(trc.d_algoName, q->d_tsig_algo);
437 if (q->d_tsig_algo == TSIG_GSS) {
438 GssContext gssctx(keyname);
439 if (!gssctx.getPeerPrincipal(q->d_peer_principal)) {
440 g_log<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<keyname<<"'"<<endl;
441 }
442 }
443 }
444
445 DNSSECKeeper dk(s_P->getBackend());
446
447 if (q->d_tsig_algo == TSIG_GSS) {
448 vector<string> princs;
449 s_P->getBackend()->getDomainMetadata(q->qdomain, "GSS-ALLOW-AXFR-PRINCIPAL", princs);
450 for(const std::string& princ : princs) {
451 if (q->d_peer_principal == princ) {
452 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: TSIG signed request with authorized principal '"<<q->d_peer_principal<<"' and algorithm 'gss-tsig'"<<endl;
453 return true;
454 }
455 }
456 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' denied: TSIG signed request with principal '"<<q->d_peer_principal<<"' and algorithm 'gss-tsig' is not permitted"<<endl;
457 return false;
458 }
459
460 if(!dk.TSIGGrantsAccess(q->qdomain, keyname)) {
461 g_log<<Logger::Error<<"AXFR '"<<q->qdomain<<"' denied: key with name '"<<keyname<<"' and algorithm '"<<getTSIGAlgoName(q->d_tsig_algo)<<"' does not grant access to zone"<<endl;
462 return false;
463 }
464 else {
465 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: TSIG signed request with authorized key '"<<keyname<<"' and algorithm '"<<getTSIGAlgoName(q->d_tsig_algo)<<"'"<<endl;
466 return true;
467 }
468 }
469
470 // cerr<<"checking allow-axfr-ips"<<endl;
471 if(!(::arg()["allow-axfr-ips"].empty()) && d_ng.match( (ComboAddress *) &q->d_remote )) {
472 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in allow-axfr-ips"<<endl;
473 return true;
474 }
475
476 FindNS fns;
477
478 // cerr<<"doing per-zone-axfr-acls"<<endl;
479 SOAData sd;
480 if(s_P->getBackend()->getSOAUncached(q->qdomain,sd)) {
481 // cerr<<"got backend and SOA"<<endl;
482 DNSBackend *B=sd.db;
483 vector<string> acl;
484 s_P->getBackend()->getDomainMetadata(q->qdomain, "ALLOW-AXFR-FROM", acl);
485 for (vector<string>::const_iterator i = acl.begin(); i != acl.end(); ++i) {
486 // cerr<<"matching against "<<*i<<endl;
487 if(pdns_iequals(*i, "AUTO-NS")) {
488 // cerr<<"AUTO-NS magic please!"<<endl;
489
490 DNSResourceRecord rr;
491 set<DNSName> nsset;
492
493 B->lookup(QType(QType::NS),q->qdomain,sd.domain_id);
494 while(B->get(rr))
495 nsset.insert(DNSName(rr.content));
496 for(const auto & j: nsset) {
497 vector<string> nsips=fns.lookup(j, s_P->getBackend());
498 for(vector<string>::const_iterator k=nsips.begin();k!=nsips.end();++k) {
499 // cerr<<"got "<<*k<<" from AUTO-NS"<<endl;
500 if(*k == q->getRemote().toString())
501 {
502 // cerr<<"got AUTO-NS hit"<<endl;
503 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in NSset"<<endl;
504 return true;
505 }
506 }
507 }
508 }
509 else
510 {
511 Netmask nm = Netmask(*i);
512 if(nm.match( (ComboAddress *) &q->d_remote ))
513 {
514 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in per-domain ACL"<<endl;
515 // cerr<<"hit!"<<endl;
516 return true;
517 }
518 }
519 }
520 }
521
522 extern CommunicatorClass Communicator;
523
524 if(Communicator.justNotified(q->qdomain, q->getRemote().toString())) { // we just notified this ip
525 g_log<<Logger::Warning<<"Approved AXFR of '"<<q->qdomain<<"' from recently notified slave "<<q->getRemote()<<endl;
526 return true;
527 }
528
529 g_log<<Logger::Error<<"AXFR of domain '"<<q->qdomain<<"' denied: client IP "<<q->getRemote()<<" has no permission"<<endl;
530 return false;
531 }
532
533 namespace {
534 struct NSECXEntry
535 {
536 NSECBitmap d_set;
537 unsigned int d_ttl;
538 bool d_auth;
539 };
540
541 static std::unique_ptr<DNSPacket> getFreshAXFRPacket(std::unique_ptr<DNSPacket>& q)
542 {
543 std::unique_ptr<DNSPacket> ret = std::unique_ptr<DNSPacket>(q->replyPacket());
544 ret->setCompress(false);
545 ret->d_dnssecOk=false; // RFC 5936, 2.2.5
546 ret->d_tcp = true;
547 return ret;
548 }
549 }
550
551
552 /** do the actual zone transfer. Return 0 in case of error, 1 in case of success */
553 int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q, int outsock)
554 {
555 std::unique_ptr<DNSPacket> outpacket= getFreshAXFRPacket(q);
556 if(q->d_dnssecOk)
557 outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
558
559 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' initiated by "<<q->getRemote()<<endl;
560
561 // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
562 SOAData sd;
563 {
564 Lock l(&s_plock);
565 DLOG(g_log<<"Looking for SOA"<<endl); // find domain_id via SOA and list complete domain. No SOA, no AXFR
566 if(!s_P) {
567 g_log<<Logger::Error<<"TCP server is without backend connections in doAXFR, launching"<<endl;
568 s_P=make_unique<PacketHandler>();
569 }
570
571 // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
572 if (!canDoAXFR(q)) {
573 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: "<<q->getRemote()<<" may not request AXFR"<<endl;
574 outpacket->setRcode(RCode::NotAuth);
575 sendPacket(outpacket,outsock);
576 return 0;
577 }
578
579 if(!s_P->getBackend()->getSOAUncached(target, sd)) {
580 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative"<<endl;
581 outpacket->setRcode(RCode::NotAuth);
582 sendPacket(outpacket,outsock);
583 return 0;
584 }
585 }
586
587 UeberBackend db;
588 if(!db.getSOAUncached(target, sd)) {
589 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative in second instance"<<endl;
590 outpacket->setRcode(RCode::NotAuth);
591 sendPacket(outpacket,outsock);
592 return 0;
593 }
594
595 DNSSECKeeper dk(&db);
596 dk.clearCaches(target);
597 bool securedZone = dk.isSecuredZone(target);
598 bool presignedZone = dk.isPresigned(target);
599
600 bool noAXFRBecauseOfNSEC3Narrow=false;
601 NSEC3PARAMRecordContent ns3pr;
602 bool narrow;
603 bool NSEC3Zone=false;
604 if(securedZone && dk.getNSEC3PARAM(target, &ns3pr, &narrow)) {
605 NSEC3Zone=true;
606 if(narrow) {
607 g_log<<Logger::Error<<"Not doing AXFR of an NSEC3 narrow zone '"<<target<<"' for "<<q->getRemote()<<endl;
608 noAXFRBecauseOfNSEC3Narrow=true;
609 }
610 }
611
612 if(noAXFRBecauseOfNSEC3Narrow) {
613 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' denied to "<<q->getRemote()<<endl;
614 outpacket->setRcode(RCode::Refused);
615 // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
616 sendPacket(outpacket,outsock);
617 return 0;
618 }
619
620 TSIGRecordContent trc;
621 DNSName tsigkeyname;
622 string tsigsecret;
623
624 bool haveTSIGDetails = q->getTSIGDetails(&trc, &tsigkeyname);
625
626 if(haveTSIGDetails && !tsigkeyname.empty()) {
627 string tsig64;
628 DNSName algorithm=trc.d_algoName; // FIXME400: check
629 if (algorithm == DNSName("hmac-md5.sig-alg.reg.int"))
630 algorithm = DNSName("hmac-md5");
631 if (algorithm != DNSName("gss-tsig")) {
632 if(!db.getTSIGKey(tsigkeyname, &algorithm, &tsig64)) {
633 g_log<<Logger::Error<<"TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"' not found"<<endl;
634 return 0;
635 }
636 if (B64Decode(tsig64, tsigsecret) == -1) {
637 g_log<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"'"<<endl;
638 return 0;
639 }
640 }
641 }
642
643
644 // SOA *must* go out first, our signing pipe might reorder
645 DLOG(g_log<<"Sending out SOA"<<endl);
646 DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd);
647 outpacket->addRecord(soa);
648 if(securedZone && !presignedZone) {
649 set<DNSName> authSet;
650 authSet.insert(target);
651 addRRSigs(dk, db, authSet, outpacket->getRRS());
652 }
653
654 if(haveTSIGDetails && !tsigkeyname.empty())
655 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal'
656
657 sendPacket(outpacket, outsock);
658
659 trc.d_mac = outpacket->d_trc.d_mac;
660 outpacket = getFreshAXFRPacket(q);
661
662 ChunkedSigningPipe csp(target, (securedZone && !presignedZone), ::arg().asNum("signing-threads", 1));
663
664 typedef map<DNSName, NSECXEntry, CanonDNSNameCompare> nsecxrepo_t;
665 nsecxrepo_t nsecxrepo;
666
667 // this is where the DNSKEYs go in
668
669 DNSSECKeeper::keyset_t keys = dk.getKeys(target);
670
671 DNSZoneRecord zrr;
672
673 zrr.dr.d_name = target;
674 zrr.dr.d_ttl = sd.default_ttl;
675 zrr.auth = 1; // please sign!
676
677 string publishCDNSKEY, publishCDS;
678 dk.getFromMeta(q->qdomain, "PUBLISH-CDNSKEY", publishCDNSKEY);
679 dk.getFromMeta(q->qdomain, "PUBLISH-CDS", publishCDS);
680 vector<DNSZoneRecord> cds, cdnskey;
681 DNSSECKeeper::keyset_t entryPoints = dk.getEntryPoints(q->qdomain);
682 set<uint32_t> entryPointIds;
683 for (auto const& value : entryPoints)
684 entryPointIds.insert(value.second.id);
685
686 for(const DNSSECKeeper::keyset_t::value_type& value : keys) {
687 zrr.dr.d_type = QType::DNSKEY;
688 zrr.dr.d_content = std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
689 DNSName keyname = NSEC3Zone ? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name))) : zrr.dr.d_name;
690 NSECXEntry& ne = nsecxrepo[keyname];
691
692 ne.d_set.set(zrr.dr.d_type);
693 ne.d_ttl = sd.default_ttl;
694 csp.submit(zrr);
695
696 // generate CDS and CDNSKEY records
697 if(entryPointIds.count(value.second.id) > 0){
698 if(publishCDNSKEY == "1") {
699 zrr.dr.d_type=QType::CDNSKEY;
700 zrr.dr.d_content = std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
701 cdnskey.push_back(zrr);
702 }
703
704 if(!publishCDS.empty()){
705 zrr.dr.d_type=QType::CDS;
706 vector<string> digestAlgos;
707 stringtok(digestAlgos, publishCDS, ", ");
708 for(auto const &digestAlgo : digestAlgos) {
709 zrr.dr.d_content=std::make_shared<DSRecordContent>(makeDSFromDNSKey(target, value.first.getDNSKEY(), pdns_stou(digestAlgo)));
710 cds.push_back(zrr);
711 }
712 }
713 }
714 }
715
716 if(::arg().mustDo("direct-dnskey")) {
717 sd.db->lookup(QType(QType::DNSKEY), target, sd.domain_id);
718 while(sd.db->get(zrr)) {
719 zrr.dr.d_ttl = sd.default_ttl;
720 csp.submit(zrr);
721 }
722 }
723
724 uint8_t flags;
725
726 if(NSEC3Zone) { // now stuff in the NSEC3PARAM
727 flags = ns3pr.d_flags;
728 zrr.dr.d_type = QType::NSEC3PARAM;
729 ns3pr.d_flags = 0;
730 zrr.dr.d_content = std::make_shared<NSEC3PARAMRecordContent>(ns3pr);
731 ns3pr.d_flags = flags;
732 DNSName keyname = DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name)));
733 NSECXEntry& ne = nsecxrepo[keyname];
734
735 ne.d_set.set(zrr.dr.d_type);
736 csp.submit(zrr);
737 }
738
739 // now start list zone
740 if(!(sd.db->list(target, sd.domain_id))) {
741 g_log<<Logger::Error<<"Backend signals error condition"<<endl;
742 outpacket->setRcode(RCode::ServFail);
743 sendPacket(outpacket,outsock);
744 return 0;
745 }
746
747
748 const bool rectify = !(presignedZone || ::arg().mustDo("disable-axfr-rectify"));
749 set<DNSName> qnames, nsset, terms;
750 vector<DNSZoneRecord> zrrs;
751
752 // Add the CDNSKEY and CDS records we created earlier
753 for (auto const &synth_zrr : cds)
754 zrrs.push_back(synth_zrr);
755
756 for (auto const &synth_zrr : cdnskey)
757 zrrs.push_back(synth_zrr);
758
759 while(sd.db->get(zrr)) {
760 zrr.dr.d_name.makeUsLowerCase();
761 if(zrr.dr.d_name.isPartOf(target)) {
762 if (zrr.dr.d_type == QType::ALIAS && ::arg().mustDo("outgoing-axfr-expand-alias")) {
763 vector<DNSZoneRecord> ips;
764 int ret1 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->d_content, QType::A, ips);
765 int ret2 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->d_content, QType::AAAA, ips);
766 if(ret1 != RCode::NoError || ret2 != RCode::NoError) {
767 g_log<<Logger::Error<<"Error resolving for ALIAS "<<zrr.dr.d_content->getZoneRepresentation()<<", aborting AXFR"<<endl;
768 outpacket->setRcode(RCode::ServFail);
769 sendPacket(outpacket,outsock);
770 return 0;
771 }
772 for(const auto& ip: ips) {
773 zrr.dr.d_type = ip.dr.d_type;
774 zrr.dr.d_content = ip.dr.d_content;
775 zrrs.push_back(zrr);
776 }
777 continue;
778 }
779
780 if (rectify) {
781 if (zrr.dr.d_type) {
782 qnames.insert(zrr.dr.d_name);
783 if(zrr.dr.d_type == QType::NS && zrr.dr.d_name!=target)
784 nsset.insert(zrr.dr.d_name);
785 } else {
786 // remove existing ents
787 continue;
788 }
789 }
790 zrrs.push_back(zrr);
791 } else {
792 if (zrr.dr.d_type)
793 g_log<<Logger::Warning<<"Zone '"<<target<<"' contains out-of-zone data '"<<zrr.dr.d_name<<"|"<<DNSRecordContent::NumberToType(zrr.dr.d_type)<<"', ignoring"<<endl;
794 }
795 }
796
797 // Group records by name and type, signpipe stumbles over interrupted rrsets
798 if(securedZone && !presignedZone) {
799 sort(zrrs.begin(), zrrs.end(), [](const DNSZoneRecord& a, const DNSZoneRecord& b) {
800 return tie(a.dr.d_name, a.dr.d_type) < tie(b.dr.d_name, b.dr.d_type);
801 });
802 }
803
804 if(rectify) {
805 // set auth
806 for(DNSZoneRecord &loopZRR : zrrs) {
807 loopZRR.auth=true;
808 if (loopZRR.dr.d_type != QType::NS || loopZRR.dr.d_name!=target) {
809 DNSName shorter(loopZRR.dr.d_name);
810 do {
811 if (shorter==target) // apex is always auth
812 break;
813 if(nsset.count(shorter) && !(loopZRR.dr.d_name==shorter && loopZRR.dr.d_type == QType::DS)) {
814 loopZRR.auth=false;
815 break;
816 }
817 } while(shorter.chopOff());
818 }
819 }
820
821 if(NSEC3Zone) {
822 // ents are only required for NSEC3 zones
823 uint32_t maxent = ::arg().asNum("max-ent-entries");
824 set<DNSName> nsec3set, nonterm;
825 for (auto &loopZRR: zrrs) {
826 bool skip=false;
827 DNSName shorter = loopZRR.dr.d_name;
828 if (shorter != target && shorter.chopOff() && shorter != target) {
829 do {
830 if(nsset.count(shorter)) {
831 skip=true;
832 break;
833 }
834 } while(shorter.chopOff() && shorter != target);
835 }
836 shorter = loopZRR.dr.d_name;
837 if(!skip && (loopZRR.dr.d_type != QType::NS || !ns3pr.d_flags)) {
838 do {
839 if(!nsec3set.count(shorter)) {
840 nsec3set.insert(shorter);
841 }
842 } while(shorter != target && shorter.chopOff());
843 }
844 }
845
846 for(DNSZoneRecord &loopZRR : zrrs) {
847 DNSName shorter(loopZRR.dr.d_name);
848 while(shorter != target && shorter.chopOff()) {
849 if(!qnames.count(shorter) && !nonterm.count(shorter) && nsec3set.count(shorter)) {
850 if(!(maxent)) {
851 g_log<<Logger::Warning<<"Zone '"<<target<<"' has too many empty non terminals."<<endl;
852 return 0;
853 }
854 nonterm.insert(shorter);
855 --maxent;
856 }
857 }
858 }
859
860 for(const auto& nt : nonterm) {
861 DNSZoneRecord tempRR;
862 tempRR.dr.d_name=nt;
863 tempRR.dr.d_type=QType::ENT;
864 tempRR.auth=true;
865 zrrs.push_back(tempRR);
866 }
867 }
868 }
869
870
871 /* now write all other records */
872
873 DNSName keyname;
874 unsigned int udiff;
875 DTime dt;
876 dt.set();
877 int records=0;
878 for(DNSZoneRecord &loopZRR : zrrs) {
879 if (!presignedZone && loopZRR.dr.d_type == QType::RRSIG)
880 continue;
881
882 // only skip the DNSKEY, CDNSKEY and CDS if direct-dnskey is enabled, to avoid changing behaviour
883 // when it is not enabled.
884 if(::arg().mustDo("direct-dnskey") && (loopZRR.dr.d_type == QType::DNSKEY || loopZRR.dr.d_type == QType::CDNSKEY || loopZRR.dr.d_type == QType::CDS))
885 continue;
886
887 records++;
888 if(securedZone && (loopZRR.auth || loopZRR.dr.d_type == QType::NS)) {
889 if (NSEC3Zone || loopZRR.dr.d_type) {
890 if (presignedZone && NSEC3Zone && loopZRR.dr.d_type == QType::RRSIG && getRR<RRSIGRecordContent>(loopZRR.dr)->d_type == QType::NSEC3) {
891 keyname = loopZRR.dr.d_name.makeRelative(sd.qname);
892 } else {
893 keyname = NSEC3Zone ? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, loopZRR.dr.d_name))) : loopZRR.dr.d_name;
894 }
895 NSECXEntry& ne = nsecxrepo[keyname];
896 ne.d_ttl = sd.default_ttl;
897 ne.d_auth = (ne.d_auth || loopZRR.auth || (NSEC3Zone && (!ns3pr.d_flags)));
898 if (loopZRR.dr.d_type && loopZRR.dr.d_type != QType::RRSIG) {
899 ne.d_set.set(loopZRR.dr.d_type);
900 }
901 }
902 }
903
904 if (!loopZRR.dr.d_type)
905 continue; // skip empty non-terminals
906
907 if(loopZRR.dr.d_type == QType::SOA)
908 continue; // skip SOA - would indicate end of AXFR
909
910 if(csp.submit(loopZRR)) {
911 for(;;) {
912 outpacket->getRRS() = csp.getChunk();
913 if(!outpacket->getRRS().empty()) {
914 if(haveTSIGDetails && !tsigkeyname.empty())
915 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
916 sendPacket(outpacket, outsock);
917 trc.d_mac=outpacket->d_trc.d_mac;
918 outpacket=getFreshAXFRPacket(q);
919 }
920 else
921 break;
922 }
923 }
924 }
925 /*
926 udiff=dt.udiffNoReset();
927 cerr<<"Starting NSEC: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
928 cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
929 cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
930 */
931 if(securedZone) {
932 if(NSEC3Zone) {
933 for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
934 if(iter->second.d_auth) {
935 NSEC3RecordContent n3rc;
936 n3rc.set(iter->second.d_set);
937 const auto numberOfTypesSet = n3rc.numberOfTypesSet();
938 if (numberOfTypesSet != 0 && (numberOfTypesSet != 1 || !n3rc.isSet(QType::NS))) {
939 n3rc.set(QType::RRSIG);
940 }
941 n3rc.d_salt = ns3pr.d_salt;
942 n3rc.d_flags = ns3pr.d_flags;
943 n3rc.d_iterations = ns3pr.d_iterations;
944 n3rc.d_algorithm = DNSSECKeeper::DIGEST_SHA1; // SHA1, fixed in PowerDNS for now
945 nsecxrepo_t::const_iterator inext = iter;
946 ++inext;
947 if(inext == nsecxrepo.end())
948 inext = nsecxrepo.begin();
949 while(!inext->second.d_auth && inext != iter)
950 {
951 ++inext;
952 if(inext == nsecxrepo.end())
953 inext = nsecxrepo.begin();
954 }
955 n3rc.d_nexthash = fromBase32Hex(inext->first.toStringNoDot());
956 zrr.dr.d_name = iter->first+sd.qname;
957
958 zrr.dr.d_ttl = sd.default_ttl;
959 zrr.dr.d_content = std::make_shared<NSEC3RecordContent>(std::move(n3rc));
960 zrr.dr.d_type = QType::NSEC3;
961 zrr.dr.d_place = DNSResourceRecord::ANSWER;
962 zrr.auth=true;
963 if(csp.submit(zrr)) {
964 for(;;) {
965 outpacket->getRRS() = csp.getChunk();
966 if(!outpacket->getRRS().empty()) {
967 if(haveTSIGDetails && !tsigkeyname.empty())
968 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
969 sendPacket(outpacket, outsock);
970 trc.d_mac=outpacket->d_trc.d_mac;
971 outpacket=getFreshAXFRPacket(q);
972 }
973 else
974 break;
975 }
976 }
977 }
978 }
979 }
980 else for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
981 NSECRecordContent nrc;
982 nrc.set(iter->second.d_set);
983 nrc.set(QType::RRSIG);
984 nrc.set(QType::NSEC);
985
986 if(boost::next(iter) != nsecxrepo.end())
987 nrc.d_next = boost::next(iter)->first;
988 else
989 nrc.d_next=nsecxrepo.begin()->first;
990 zrr.dr.d_name = iter->first;
991
992 zrr.dr.d_ttl = sd.default_ttl;
993 zrr.dr.d_content = std::make_shared<NSECRecordContent>(std::move(nrc));
994 zrr.dr.d_type = QType::NSEC;
995 zrr.dr.d_place = DNSResourceRecord::ANSWER;
996 zrr.auth=true;
997 if(csp.submit(zrr)) {
998 for(;;) {
999 outpacket->getRRS() = csp.getChunk();
1000 if(!outpacket->getRRS().empty()) {
1001 if(haveTSIGDetails && !tsigkeyname.empty())
1002 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
1003 sendPacket(outpacket, outsock);
1004 trc.d_mac=outpacket->d_trc.d_mac;
1005 outpacket=getFreshAXFRPacket(q);
1006 }
1007 else
1008 break;
1009 }
1010 }
1011 }
1012 }
1013 /*
1014 udiff=dt.udiffNoReset();
1015 cerr<<"Flushing pipe: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
1016 cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
1017 cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
1018 * */
1019 for(;;) {
1020 outpacket->getRRS() = csp.getChunk(true); // flush the pipe
1021 if(!outpacket->getRRS().empty()) {
1022 if(haveTSIGDetails && !tsigkeyname.empty())
1023 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); // first answer is 'normal'
1024 sendPacket(outpacket, outsock);
1025 trc.d_mac=outpacket->d_trc.d_mac;
1026 outpacket=getFreshAXFRPacket(q);
1027 }
1028 else
1029 break;
1030 }
1031
1032 udiff=dt.udiffNoReset();
1033 if(securedZone)
1034 g_log<<Logger::Info<<"Done signing: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<endl;
1035
1036 DLOG(g_log<<"Done writing out records"<<endl);
1037 /* and terminate with yet again the SOA record */
1038 outpacket=getFreshAXFRPacket(q);
1039 outpacket->addRecord(soa);
1040 if(haveTSIGDetails && !tsigkeyname.empty())
1041 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
1042
1043 sendPacket(outpacket, outsock);
1044
1045 DLOG(g_log<<"last packet - close"<<endl);
1046 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' to "<<q->getRemote()<<" finished"<<endl;
1047
1048 return 1;
1049 }
1050
1051 int TCPNameserver::doIXFR(std::unique_ptr<DNSPacket>& q, int outsock)
1052 {
1053 std::unique_ptr<DNSPacket> outpacket=getFreshAXFRPacket(q);
1054 if(q->d_dnssecOk)
1055 outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
1056
1057 uint32_t serial = 0;
1058 MOADNSParser mdp(false, q->getString());
1059 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) {
1060 const DNSRecord *rr = &i->first;
1061 if (rr->d_type == QType::SOA && rr->d_place == DNSResourceRecord::AUTHORITY) {
1062 vector<string>parts;
1063 stringtok(parts, rr->d_content->getZoneRepresentation());
1064 if (parts.size() >= 3) {
1065 try {
1066 serial=pdns_stou(parts[2]);
1067 }
1068 catch(const std::out_of_range& oor) {
1069 g_log<<Logger::Error<<"Invalid serial in IXFR query"<<endl;
1070 outpacket->setRcode(RCode::FormErr);
1071 sendPacket(outpacket,outsock);
1072 return 0;
1073 }
1074 } else {
1075 g_log<<Logger::Error<<"No serial in IXFR query"<<endl;
1076 outpacket->setRcode(RCode::FormErr);
1077 sendPacket(outpacket,outsock);
1078 return 0;
1079 }
1080 } else if (rr->d_type != QType::TSIG && rr->d_type != QType::OPT) {
1081 g_log<<Logger::Error<<"Additional records in IXFR query, type: "<<QType(rr->d_type).getName()<<endl;
1082 outpacket->setRcode(RCode::FormErr);
1083 sendPacket(outpacket,outsock);
1084 return 0;
1085 }
1086 }
1087
1088 g_log<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' initiated by "<<q->getRemote()<<" with serial "<<serial<<endl;
1089
1090 // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
1091 SOAData sd;
1092 {
1093 Lock l(&s_plock);
1094 DLOG(g_log<<"Looking for SOA"<<endl); // find domain_id via SOA and list complete domain. No SOA, no IXFR
1095 if(!s_P) {
1096 g_log<<Logger::Error<<"TCP server is without backend connections in doIXFR, launching"<<endl;
1097 s_P=make_unique<PacketHandler>();
1098 }
1099
1100 // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
1101 if(!canDoAXFR(q) || !s_P->getBackend()->getSOAUncached(q->qdomain, sd)) {
1102 g_log<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' failed: not authoritative"<<endl;
1103 outpacket->setRcode(RCode::NotAuth);
1104 sendPacket(outpacket,outsock);
1105 return 0;
1106 }
1107 }
1108
1109 DNSSECKeeper dk;
1110 NSEC3PARAMRecordContent ns3pr;
1111 bool narrow;
1112
1113 dk.clearCaches(q->qdomain);
1114 bool securedZone = dk.isSecuredZone(q->qdomain);
1115 if(dk.getNSEC3PARAM(q->qdomain, &ns3pr, &narrow)) {
1116 if(narrow) {
1117 g_log<<Logger::Error<<"Not doing IXFR of an NSEC3 narrow zone."<<endl;
1118 g_log<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' denied to "<<q->getRemote()<<endl;
1119 outpacket->setRcode(RCode::Refused);
1120 sendPacket(outpacket,outsock);
1121 return 0;
1122 }
1123 }
1124
1125 DNSName target = q->qdomain;
1126
1127 UeberBackend db;
1128 if(!db.getSOAUncached(target, sd)) {
1129 g_log<<Logger::Error<<"IXFR of domain '"<<target<<"' failed: not authoritative in second instance"<<endl;
1130 outpacket->setRcode(RCode::NotAuth);
1131 sendPacket(outpacket,outsock);
1132 return 0;
1133 }
1134
1135 if (!rfc1982LessThan(serial, calculateEditSOA(sd.serial, dk, sd.qname))) {
1136 TSIGRecordContent trc;
1137 DNSName tsigkeyname;
1138 string tsigsecret;
1139
1140 bool haveTSIGDetails = q->getTSIGDetails(&trc, &tsigkeyname);
1141
1142 if(haveTSIGDetails && !tsigkeyname.empty()) {
1143 string tsig64;
1144 DNSName algorithm=trc.d_algoName; // FIXME400: was toLowerCanonic, compare output
1145 if (algorithm == DNSName("hmac-md5.sig-alg.reg.int"))
1146 algorithm = DNSName("hmac-md5");
1147 Lock l(&s_plock);
1148 if(!s_P->getBackend()->getTSIGKey(tsigkeyname, &algorithm, &tsig64)) {
1149 g_log<<Logger::Error<<"TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"' not found"<<endl;
1150 return 0;
1151 }
1152 if (B64Decode(tsig64, tsigsecret) == -1) {
1153 g_log<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"'"<<endl;
1154 return 0;
1155 }
1156 }
1157
1158 UeberBackend signatureDB;
1159
1160 // SOA *must* go out first, our signing pipe might reorder
1161 DLOG(g_log<<"Sending out SOA"<<endl);
1162 DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd);
1163 outpacket->addRecord(soa);
1164 if(securedZone) {
1165 set<DNSName> authSet;
1166 authSet.insert(target);
1167 addRRSigs(dk, signatureDB, authSet, outpacket->getRRS());
1168 }
1169
1170 if(haveTSIGDetails && !tsigkeyname.empty())
1171 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal'
1172
1173 sendPacket(outpacket, outsock);
1174
1175 g_log<<Logger::Error<<"IXFR of domain '"<<target<<"' to "<<q->getRemote()<<" finished"<<endl;
1176
1177 return 1;
1178 }
1179
1180 g_log<<Logger::Error<<"IXFR fallback to AXFR for domain '"<<target<<"' our serial "<<sd.serial<<endl;
1181 return doAXFR(q->qdomain, q, outsock);
1182 }
1183
1184 TCPNameserver::~TCPNameserver()
1185 {
1186 }
1187
1188 TCPNameserver::TCPNameserver()
1189 {
1190 d_maxTransactionsPerConn = ::arg().asNum("max-tcp-transactions-per-conn");
1191 d_idleTimeout = ::arg().asNum("tcp-idle-timeout");
1192 d_maxConnectionDuration = ::arg().asNum("max-tcp-connection-duration");
1193 d_maxConnectionsPerClient = ::arg().asNum("max-tcp-connections-per-client");
1194
1195 // sem_init(&d_connectionroom_sem,0,::arg().asNum("max-tcp-connections"));
1196 d_connectionroom_sem = make_unique<Semaphore>( ::arg().asNum( "max-tcp-connections" ));
1197 d_maxTCPConnections = ::arg().asNum( "max-tcp-connections" );
1198 d_tid=0;
1199 vector<string>locals;
1200 stringtok(locals,::arg()["local-address"]," ,");
1201
1202 vector<string>locals6;
1203 stringtok(locals6,::arg()["local-ipv6"]," ,");
1204
1205 if(locals.empty() && locals6.empty())
1206 throw PDNSException("No local address specified");
1207
1208 d_ng.toMasks(::arg()["allow-axfr-ips"] );
1209
1210 signal(SIGPIPE,SIG_IGN);
1211
1212 for(vector<string>::const_iterator laddr=locals.begin();laddr!=locals.end();++laddr) {
1213 int s=socket(AF_INET,SOCK_STREAM,0);
1214
1215 if(s<0)
1216 throw PDNSException("Unable to acquire TCP socket: "+stringerror());
1217
1218 setCloseOnExec(s);
1219
1220 ComboAddress local(*laddr, ::arg().asNum("local-port"));
1221
1222 int tmp=1;
1223 if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
1224 g_log<<Logger::Error<<"Setsockopt failed"<<endl;
1225 _exit(1);
1226 }
1227
1228 if (::arg().asNum("tcp-fast-open") > 0) {
1229 #ifdef TCP_FASTOPEN
1230 int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
1231 if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
1232 g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<stringerror()<<endl;
1233 }
1234 #else
1235 g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
1236 #endif
1237 }
1238
1239 if( ::arg().mustDo("non-local-bind") )
1240 Utility::setBindAny(AF_INET, s);
1241
1242 if(::bind(s, (sockaddr*)&local, local.getSocklen())<0) {
1243 int err = errno;
1244 close(s);
1245 if( err == EADDRNOTAVAIL && ! ::arg().mustDo("local-address-nonexist-fail") ) {
1246 g_log<<Logger::Error<<"IPv4 Address " << *laddr << " does not exist on this server - skipping TCP bind" << endl;
1247 continue;
1248 } else {
1249 g_log<<Logger::Error<<"Unable to bind to TCP socket " << *laddr << ": "<<stringerror(err)<<endl;
1250 throw PDNSException("Unable to bind to TCP socket");
1251 }
1252 }
1253
1254 listen(s,128);
1255 g_log<<Logger::Error<<"TCP server bound to "<<local.toStringWithPort()<<endl;
1256 d_sockets.push_back(s);
1257 struct pollfd pfd;
1258 memset(&pfd, 0, sizeof(pfd));
1259 pfd.fd = s;
1260 pfd.events = POLLIN;
1261
1262 d_prfds.push_back(pfd);
1263 }
1264
1265 for(vector<string>::const_iterator laddr=locals6.begin();laddr!=locals6.end();++laddr) {
1266 int s=socket(AF_INET6,SOCK_STREAM,0);
1267
1268 if(s<0)
1269 throw PDNSException("Unable to acquire TCPv6 socket: "+stringerror());
1270
1271 setCloseOnExec(s);
1272
1273 ComboAddress local(*laddr, ::arg().asNum("local-port"));
1274
1275 int tmp=1;
1276 if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
1277 g_log<<Logger::Error<<"Setsockopt failed"<<endl;
1278 _exit(1);
1279 }
1280
1281 if (::arg().asNum("tcp-fast-open") > 0) {
1282 #ifdef TCP_FASTOPEN
1283 int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
1284 if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
1285 g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<stringerror()<<endl;
1286 }
1287 #else
1288 g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
1289 #endif
1290 }
1291
1292 if( ::arg().mustDo("non-local-bind") )
1293 Utility::setBindAny(AF_INET6, s);
1294 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
1295 g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<stringerror()<<endl;
1296 }
1297 if(bind(s, (const sockaddr*)&local, local.getSocklen())<0) {
1298 int err = errno;
1299 close(s);
1300 if( err == EADDRNOTAVAIL && ! ::arg().mustDo("local-ipv6-nonexist-fail") ) {
1301 g_log<<Logger::Error<<"IPv6 Address " << *laddr << " does not exist on this server - skipping TCP bind" << endl;
1302 continue;
1303 } else {
1304 g_log<<Logger::Error<<"Unable to bind to TCPv6 socket" << *laddr << ": "<<stringerror(err)<<endl;
1305 throw PDNSException("Unable to bind to TCPv6 socket");
1306 }
1307 }
1308
1309 listen(s,128);
1310 g_log<<Logger::Error<<"TCPv6 server bound to "<<local.toStringWithPort()<<endl; // this gets %eth0 right
1311 d_sockets.push_back(s);
1312
1313 struct pollfd pfd;
1314 memset(&pfd, 0, sizeof(pfd));
1315 pfd.fd = s;
1316 pfd.events = POLLIN;
1317
1318 d_prfds.push_back(pfd);
1319 }
1320 }
1321
1322
1323 //! Start of TCP operations thread, we launch a new thread for each incoming TCP question
1324 void TCPNameserver::thread()
1325 {
1326 setThreadName("pdns/tcpnameser");
1327 try {
1328 for(;;) {
1329 int fd;
1330 ComboAddress remote;
1331 Utility::socklen_t addrlen=remote.getSocklen();
1332
1333 int ret=poll(&d_prfds[0], d_prfds.size(), -1); // blocks, forever if need be
1334 if(ret <= 0)
1335 continue;
1336
1337 int sock=-1;
1338 for(const pollfd& pfd : d_prfds) {
1339 if(pfd.revents & POLLIN) {
1340 sock = pfd.fd;
1341 remote.sin4.sin_family = AF_INET6;
1342 addrlen=remote.getSocklen();
1343
1344 if((fd=accept(sock, (sockaddr*)&remote, &addrlen))<0) {
1345 int err = errno;
1346 g_log<<Logger::Error<<"TCP question accept error: "<<stringerror(err)<<endl;
1347
1348 if(err==EMFILE) {
1349 g_log<<Logger::Error<<"TCP handler out of filedescriptors, exiting, won't recover from this"<<endl;
1350 _exit(1);
1351 }
1352 }
1353 else {
1354 if (d_maxConnectionsPerClient) {
1355 std::lock_guard<std::mutex> lock(s_clientsCountMutex);
1356 if (s_clientsCount[remote] >= d_maxConnectionsPerClient) {
1357 g_log<<Logger::Notice<<"Limit of simultaneous TCP connections per client reached for "<< remote<<", dropping"<<endl;
1358 close(fd);
1359 continue;
1360 }
1361 s_clientsCount[remote]++;
1362 }
1363
1364 pthread_t tid;
1365 d_connectionroom_sem->wait(); // blocks if no connections are available
1366
1367 int room;
1368 d_connectionroom_sem->getValue( &room);
1369 if(room<1)
1370 g_log<<Logger::Warning<<"Limit of simultaneous TCP connections reached - raise max-tcp-connections"<<endl;
1371
1372 int err;
1373 if((err = pthread_create(&tid, 0, &doConnection, reinterpret_cast<void*>(fd)))) {
1374 g_log<<Logger::Error<<"Error creating thread: "<<stringerror(err)<<endl;
1375 d_connectionroom_sem->post();
1376 close(fd);
1377 decrementClientCount(remote);
1378 }
1379 }
1380 }
1381 }
1382 }
1383 }
1384 catch(PDNSException &AE) {
1385 g_log<<Logger::Error<<"TCP Nameserver thread dying because of fatal error: "<<AE.reason<<endl;
1386 }
1387 catch(...) {
1388 g_log<<Logger::Error<<"TCPNameserver dying because of an unexpected fatal error"<<endl;
1389 }
1390 _exit(1); // take rest of server with us
1391 }
1392
1393
1394 unsigned int TCPNameserver::numTCPConnections()
1395 {
1396 int room;
1397 d_connectionroom_sem->getValue( &room);
1398 return d_maxTCPConnections - room;
1399 }