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