]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/tcpreceiver.cc
Revert "Bail out when no Context library is available"
[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 unsigned int TCPNameserver::d_maxTCPConnections = 0;
72 PacketHandler *TCPNameserver::s_P;
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=0;
85 try {
86 s_P=new 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(shared_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 shared_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=shared_ptr<DNSPacket>(new 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 shared_ptr<DNSPacket> reply;
351 shared_ptr<DNSPacket> cached= shared_ptr<DNSPacket>(new 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.get(), cached.get())) { // 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=new PacketHandler;
382 }
383
384 reply=shared_ptr<DNSPacket>(s_P->doQuestion(packet.get())); // 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 delete s_P;
396 s_P = 0; // on next call, backend will be recycled
397 g_log<<Logger::Error<<"TCP nameserver had error, cycling backend: "<<ae.reason<<endl;
398 }
399 catch(NetworkError &e) {
400 g_log<<Logger::Info<<"TCP Connection Thread died because of network error: "<<e.what()<<endl;
401 }
402
403 catch(std::exception &e) {
404 g_log<<Logger::Error<<"TCP Connection Thread died because of STL error: "<<e.what()<<endl;
405 }
406 catch( ... )
407 {
408 g_log << Logger::Error << "TCP Connection Thread caught unknown exception." << endl;
409 }
410 d_connectionroom_sem->post();
411
412 try {
413 closesocket(fd);
414 }
415 catch(const PDNSException& e) {
416 g_log<<Logger::Error<<"Error closing TCP socket: "<<e.reason<<endl;
417 }
418 decrementClientCount(remote);
419
420 return 0;
421 }
422
423
424 // call this method with s_plock held!
425 bool TCPNameserver::canDoAXFR(shared_ptr<DNSPacket> q)
426 {
427 if(::arg().mustDo("disable-axfr"))
428 return false;
429
430 if(q->d_havetsig) { // if you have one, it must be good
431 TSIGRecordContent trc;
432 DNSName keyname;
433 string secret;
434 if(!q->checkForCorrectTSIG(s_P->getBackend(), &keyname, &secret, &trc)) {
435 return false;
436 } else {
437 getTSIGHashEnum(trc.d_algoName, q->d_tsig_algo);
438 if (q->d_tsig_algo == TSIG_GSS) {
439 GssContext gssctx(keyname);
440 if (!gssctx.getPeerPrincipal(q->d_peer_principal)) {
441 g_log<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<keyname<<"'"<<endl;
442 }
443 }
444 }
445
446 DNSSECKeeper dk(s_P->getBackend());
447
448 if (q->d_tsig_algo == TSIG_GSS) {
449 vector<string> princs;
450 s_P->getBackend()->getDomainMetadata(q->qdomain, "GSS-ALLOW-AXFR-PRINCIPAL", princs);
451 for(const std::string& princ : princs) {
452 if (q->d_peer_principal == princ) {
453 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;
454 return true;
455 }
456 }
457 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;
458 return false;
459 }
460
461 if(!dk.TSIGGrantsAccess(q->qdomain, keyname)) {
462 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;
463 return false;
464 }
465 else {
466 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;
467 return true;
468 }
469 }
470
471 // cerr<<"checking allow-axfr-ips"<<endl;
472 if(!(::arg()["allow-axfr-ips"].empty()) && d_ng.match( (ComboAddress *) &q->d_remote )) {
473 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in allow-axfr-ips"<<endl;
474 return true;
475 }
476
477 FindNS fns;
478
479 // cerr<<"doing per-zone-axfr-acls"<<endl;
480 SOAData sd;
481 if(s_P->getBackend()->getSOAUncached(q->qdomain,sd)) {
482 // cerr<<"got backend and SOA"<<endl;
483 DNSBackend *B=sd.db;
484 vector<string> acl;
485 s_P->getBackend()->getDomainMetadata(q->qdomain, "ALLOW-AXFR-FROM", acl);
486 for (vector<string>::const_iterator i = acl.begin(); i != acl.end(); ++i) {
487 // cerr<<"matching against "<<*i<<endl;
488 if(pdns_iequals(*i, "AUTO-NS")) {
489 // cerr<<"AUTO-NS magic please!"<<endl;
490
491 DNSResourceRecord rr;
492 set<DNSName> nsset;
493
494 B->lookup(QType(QType::NS),q->qdomain);
495 while(B->get(rr))
496 nsset.insert(DNSName(rr.content));
497 for(const auto & j: nsset) {
498 vector<string> nsips=fns.lookup(j, s_P->getBackend());
499 for(vector<string>::const_iterator k=nsips.begin();k!=nsips.end();++k) {
500 // cerr<<"got "<<*k<<" from AUTO-NS"<<endl;
501 if(*k == q->getRemote().toString())
502 {
503 // cerr<<"got AUTO-NS hit"<<endl;
504 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in NSset"<<endl;
505 return true;
506 }
507 }
508 }
509 }
510 else
511 {
512 Netmask nm = Netmask(*i);
513 if(nm.match( (ComboAddress *) &q->d_remote ))
514 {
515 g_log<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in per-domain ACL"<<endl;
516 // cerr<<"hit!"<<endl;
517 return true;
518 }
519 }
520 }
521 }
522
523 extern CommunicatorClass Communicator;
524
525 if(Communicator.justNotified(q->qdomain, q->getRemote().toString())) { // we just notified this ip
526 g_log<<Logger::Warning<<"Approved AXFR of '"<<q->qdomain<<"' from recently notified slave "<<q->getRemote()<<endl;
527 return true;
528 }
529
530 g_log<<Logger::Error<<"AXFR of domain '"<<q->qdomain<<"' denied: client IP "<<q->getRemote()<<" has no permission"<<endl;
531 return false;
532 }
533
534 namespace {
535 struct NSECXEntry
536 {
537 NSECBitmap d_set;
538 unsigned int d_ttl;
539 bool d_auth;
540 };
541
542 shared_ptr<DNSPacket> getFreshAXFRPacket(shared_ptr<DNSPacket> q)
543 {
544 shared_ptr<DNSPacket> ret = shared_ptr<DNSPacket>(q->replyPacket());
545 ret->setCompress(false);
546 ret->d_dnssecOk=false; // RFC 5936, 2.2.5
547 ret->d_tcp = true;
548 return ret;
549 }
550 }
551
552
553 /** do the actual zone transfer. Return 0 in case of error, 1 in case of success */
554 int TCPNameserver::doAXFR(const DNSName &target, shared_ptr<DNSPacket> q, int outsock)
555 {
556 shared_ptr<DNSPacket> outpacket= getFreshAXFRPacket(q);
557 if(q->d_dnssecOk)
558 outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
559
560 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' initiated by "<<q->getRemote()<<endl;
561
562 // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
563 SOAData sd;
564 {
565 Lock l(&s_plock);
566 DLOG(g_log<<"Looking for SOA"<<endl); // find domain_id via SOA and list complete domain. No SOA, no AXFR
567 if(!s_P) {
568 g_log<<Logger::Error<<"TCP server is without backend connections in doAXFR, launching"<<endl;
569 s_P=new PacketHandler;
570 }
571
572 // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
573 if (!canDoAXFR(q)) {
574 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: "<<q->getRemote()<<" may not request AXFR"<<endl;
575 outpacket->setRcode(RCode::NotAuth);
576 sendPacket(outpacket,outsock);
577 return 0;
578 }
579
580 if(!s_P->getBackend()->getSOAUncached(target, sd)) {
581 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative"<<endl;
582 outpacket->setRcode(RCode::NotAuth);
583 sendPacket(outpacket,outsock);
584 return 0;
585 }
586 }
587
588 UeberBackend db;
589 if(!db.getSOAUncached(target, sd)) {
590 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative in second instance"<<endl;
591 outpacket->setRcode(RCode::NotAuth);
592 sendPacket(outpacket,outsock);
593 return 0;
594 }
595
596 DNSSECKeeper dk(&db);
597 dk.clearCaches(target);
598 bool securedZone = dk.isSecuredZone(target);
599 bool presignedZone = dk.isPresigned(target);
600
601 bool noAXFRBecauseOfNSEC3Narrow=false;
602 NSEC3PARAMRecordContent ns3pr;
603 bool narrow;
604 bool NSEC3Zone=false;
605 if(securedZone && dk.getNSEC3PARAM(target, &ns3pr, &narrow)) {
606 NSEC3Zone=true;
607 if(narrow) {
608 g_log<<Logger::Error<<"Not doing AXFR of an NSEC3 narrow zone '"<<target<<"' for "<<q->getRemote()<<endl;
609 noAXFRBecauseOfNSEC3Narrow=true;
610 }
611 }
612
613 if(noAXFRBecauseOfNSEC3Narrow) {
614 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' denied to "<<q->getRemote()<<endl;
615 outpacket->setRcode(RCode::Refused);
616 // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
617 sendPacket(outpacket,outsock);
618 return 0;
619 }
620
621 TSIGRecordContent trc;
622 DNSName tsigkeyname;
623 string tsigsecret;
624
625 bool haveTSIGDetails = q->getTSIGDetails(&trc, &tsigkeyname);
626
627 if(haveTSIGDetails && !tsigkeyname.empty()) {
628 string tsig64;
629 DNSName algorithm=trc.d_algoName; // FIXME400: check
630 if (algorithm == DNSName("hmac-md5.sig-alg.reg.int"))
631 algorithm = DNSName("hmac-md5");
632 if (algorithm != DNSName("gss-tsig")) {
633 if(!db.getTSIGKey(tsigkeyname, &algorithm, &tsig64)) {
634 g_log<<Logger::Error<<"TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"' not found"<<endl;
635 return 0;
636 }
637 if (B64Decode(tsig64, tsigsecret) == -1) {
638 g_log<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"'"<<endl;
639 return 0;
640 }
641 }
642 }
643
644
645 // SOA *must* go out first, our signing pipe might reorder
646 DLOG(g_log<<"Sending out SOA"<<endl);
647 DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd);
648 outpacket->addRecord(soa);
649 if(securedZone && !presignedZone) {
650 set<DNSName> authSet;
651 authSet.insert(target);
652 addRRSigs(dk, db, authSet, outpacket->getRRS());
653 }
654
655 if(haveTSIGDetails && !tsigkeyname.empty())
656 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal'
657
658 sendPacket(outpacket, outsock);
659
660 trc.d_mac = outpacket->d_trc.d_mac;
661 outpacket = getFreshAXFRPacket(q);
662
663 ChunkedSigningPipe csp(target, (securedZone && !presignedZone), ::arg().asNum("signing-threads", 1));
664
665 typedef map<DNSName, NSECXEntry, CanonDNSNameCompare> nsecxrepo_t;
666 nsecxrepo_t nsecxrepo;
667
668 // this is where the DNSKEYs go in
669
670 DNSSECKeeper::keyset_t keys = dk.getKeys(target);
671
672 DNSZoneRecord zrr;
673
674 zrr.dr.d_name = target;
675 zrr.dr.d_ttl = sd.default_ttl;
676 zrr.auth = 1; // please sign!
677
678 string publishCDNSKEY, publishCDS;
679 dk.getFromMeta(q->qdomain, "PUBLISH-CDNSKEY", publishCDNSKEY);
680 dk.getFromMeta(q->qdomain, "PUBLISH-CDS", publishCDS);
681 vector<DNSZoneRecord> cds, cdnskey;
682 DNSSECKeeper::keyset_t entryPoints = dk.getEntryPoints(q->qdomain);
683 set<uint32_t> entryPointIds;
684 for (auto const& value : entryPoints)
685 entryPointIds.insert(value.second.id);
686
687 for(const DNSSECKeeper::keyset_t::value_type& value : keys) {
688 zrr.dr.d_type = QType::DNSKEY;
689 zrr.dr.d_content = std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
690 DNSName keyname = NSEC3Zone ? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name))) : zrr.dr.d_name;
691 NSECXEntry& ne = nsecxrepo[keyname];
692
693 ne.d_set.set(zrr.dr.d_type);
694 ne.d_ttl = sd.default_ttl;
695 csp.submit(zrr);
696
697 // generate CDS and CDNSKEY records
698 if(entryPointIds.count(value.second.id) > 0){
699 if(publishCDNSKEY == "1") {
700 zrr.dr.d_type=QType::CDNSKEY;
701 zrr.dr.d_content = std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
702 cdnskey.push_back(zrr);
703 }
704
705 if(!publishCDS.empty()){
706 zrr.dr.d_type=QType::CDS;
707 vector<string> digestAlgos;
708 stringtok(digestAlgos, publishCDS, ", ");
709 for(auto const &digestAlgo : digestAlgos) {
710 zrr.dr.d_content=std::make_shared<DSRecordContent>(makeDSFromDNSKey(target, value.first.getDNSKEY(), pdns_stou(digestAlgo)));
711 cds.push_back(zrr);
712 }
713 }
714 }
715 }
716
717 if(::arg().mustDo("direct-dnskey")) {
718 sd.db->lookup(QType(QType::DNSKEY), target, NULL, sd.domain_id);
719 while(sd.db->get(zrr)) {
720 zrr.dr.d_ttl = sd.default_ttl;
721 csp.submit(zrr);
722 }
723 }
724
725 uint8_t flags;
726
727 if(NSEC3Zone) { // now stuff in the NSEC3PARAM
728 flags = ns3pr.d_flags;
729 zrr.dr.d_type = QType::NSEC3PARAM;
730 ns3pr.d_flags = 0;
731 zrr.dr.d_content = std::make_shared<NSEC3PARAMRecordContent>(ns3pr);
732 ns3pr.d_flags = flags;
733 DNSName keyname = DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name)));
734 NSECXEntry& ne = nsecxrepo[keyname];
735
736 ne.d_set.set(zrr.dr.d_type);
737 csp.submit(zrr);
738 }
739
740 // now start list zone
741 if(!(sd.db->list(target, sd.domain_id))) {
742 g_log<<Logger::Error<<"Backend signals error condition"<<endl;
743 outpacket->setRcode(RCode::ServFail);
744 sendPacket(outpacket,outsock);
745 return 0;
746 }
747
748
749 const bool rectify = !(presignedZone || ::arg().mustDo("disable-axfr-rectify"));
750 set<DNSName> qnames, nsset, terms;
751 vector<DNSZoneRecord> zrrs;
752
753 // Add the CDNSKEY and CDS records we created earlier
754 for (auto const &synth_zrr : cds)
755 zrrs.push_back(synth_zrr);
756
757 for (auto const &synth_zrr : cdnskey)
758 zrrs.push_back(synth_zrr);
759
760 while(sd.db->get(zrr)) {
761 zrr.dr.d_name.makeUsLowerCase();
762 if(zrr.dr.d_name.isPartOf(target)) {
763 if (zrr.dr.d_type == QType::ALIAS && ::arg().mustDo("outgoing-axfr-expand-alias")) {
764 vector<DNSZoneRecord> ips;
765 int ret1 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->d_content, QType::A, ips);
766 int ret2 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->d_content, QType::AAAA, ips);
767 if(ret1 != RCode::NoError || ret2 != RCode::NoError) {
768 g_log<<Logger::Error<<"Error resolving for ALIAS "<<zrr.dr.d_content->getZoneRepresentation()<<", aborting AXFR"<<endl;
769 outpacket->setRcode(RCode::ServFail);
770 sendPacket(outpacket,outsock);
771 return 0;
772 }
773 for(const auto& ip: ips) {
774 zrr.dr.d_type = ip.dr.d_type;
775 zrr.dr.d_content = ip.dr.d_content;
776 zrrs.push_back(zrr);
777 }
778 continue;
779 }
780
781 if (rectify) {
782 if (zrr.dr.d_type) {
783 qnames.insert(zrr.dr.d_name);
784 if(zrr.dr.d_type == QType::NS && zrr.dr.d_name!=target)
785 nsset.insert(zrr.dr.d_name);
786 } else {
787 // remove existing ents
788 continue;
789 }
790 }
791 zrrs.push_back(zrr);
792 } else {
793 if (zrr.dr.d_type)
794 g_log<<Logger::Warning<<"Zone '"<<target<<"' contains out-of-zone data '"<<zrr.dr.d_name<<"|"<<DNSRecordContent::NumberToType(zrr.dr.d_type)<<"', ignoring"<<endl;
795 }
796 }
797
798 // Group records by name and type, signpipe stumbles over interrupted rrsets
799 if(securedZone && !presignedZone) {
800 sort(zrrs.begin(), zrrs.end(), [](const DNSZoneRecord& a, const DNSZoneRecord& b) {
801 return tie(a.dr.d_name, a.dr.d_type) < tie(b.dr.d_name, b.dr.d_type);
802 });
803 }
804
805 if(rectify) {
806 // set auth
807 for(DNSZoneRecord &loopZRR : zrrs) {
808 loopZRR.auth=true;
809 if (loopZRR.dr.d_type != QType::NS || loopZRR.dr.d_name!=target) {
810 DNSName shorter(loopZRR.dr.d_name);
811 do {
812 if (shorter==target) // apex is always auth
813 break;
814 if(nsset.count(shorter) && !(loopZRR.dr.d_name==shorter && loopZRR.dr.d_type == QType::DS)) {
815 loopZRR.auth=false;
816 break;
817 }
818 } while(shorter.chopOff());
819 }
820 }
821
822 if(NSEC3Zone) {
823 // ents are only required for NSEC3 zones
824 uint32_t maxent = ::arg().asNum("max-ent-entries");
825 set<DNSName> nsec3set, nonterm;
826 for (auto &loopZRR: zrrs) {
827 bool skip=false;
828 DNSName shorter = loopZRR.dr.d_name;
829 if (shorter != target && shorter.chopOff() && shorter != target) {
830 do {
831 if(nsset.count(shorter)) {
832 skip=true;
833 break;
834 }
835 } while(shorter.chopOff() && shorter != target);
836 }
837 shorter = loopZRR.dr.d_name;
838 if(!skip && (loopZRR.dr.d_type != QType::NS || !ns3pr.d_flags)) {
839 do {
840 if(!nsec3set.count(shorter)) {
841 nsec3set.insert(shorter);
842 }
843 } while(shorter != target && shorter.chopOff());
844 }
845 }
846
847 for(DNSZoneRecord &loopZRR : zrrs) {
848 DNSName shorter(loopZRR.dr.d_name);
849 while(shorter != target && shorter.chopOff()) {
850 if(!qnames.count(shorter) && !nonterm.count(shorter) && nsec3set.count(shorter)) {
851 if(!(maxent)) {
852 g_log<<Logger::Warning<<"Zone '"<<target<<"' has too many empty non terminals."<<endl;
853 return 0;
854 }
855 nonterm.insert(shorter);
856 --maxent;
857 }
858 }
859 }
860
861 for(const auto& nt : nonterm) {
862 DNSZoneRecord tempRR;
863 tempRR.dr.d_name=nt;
864 tempRR.dr.d_type=QType::ENT;
865 tempRR.auth=true;
866 zrrs.push_back(tempRR);
867 }
868 }
869 }
870
871
872 /* now write all other records */
873
874 DNSName keyname;
875 unsigned int udiff;
876 DTime dt;
877 dt.set();
878 int records=0;
879 for(DNSZoneRecord &loopZRR : zrrs) {
880 if (!presignedZone && loopZRR.dr.d_type == QType::RRSIG)
881 continue;
882
883 // only skip the DNSKEY, CDNSKEY and CDS if direct-dnskey is enabled, to avoid changing behaviour
884 // when it is not enabled.
885 if(::arg().mustDo("direct-dnskey") && (loopZRR.dr.d_type == QType::DNSKEY || loopZRR.dr.d_type == QType::CDNSKEY || loopZRR.dr.d_type == QType::CDS))
886 continue;
887
888 records++;
889 if(securedZone && (loopZRR.auth || loopZRR.dr.d_type == QType::NS)) {
890 if (NSEC3Zone || loopZRR.dr.d_type) {
891 if (presignedZone && NSEC3Zone && loopZRR.dr.d_type == QType::RRSIG && getRR<RRSIGRecordContent>(loopZRR.dr)->d_type == QType::NSEC3) {
892 keyname = loopZRR.dr.d_name.makeRelative(sd.qname);
893 } else {
894 keyname = NSEC3Zone ? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, loopZRR.dr.d_name))) : loopZRR.dr.d_name;
895 }
896 NSECXEntry& ne = nsecxrepo[keyname];
897 ne.d_ttl = sd.default_ttl;
898 ne.d_auth = (ne.d_auth || loopZRR.auth || (NSEC3Zone && (!ns3pr.d_flags)));
899 if (loopZRR.dr.d_type && loopZRR.dr.d_type != QType::RRSIG) {
900 ne.d_set.set(loopZRR.dr.d_type);
901 }
902 }
903 }
904
905 if (!loopZRR.dr.d_type)
906 continue; // skip empty non-terminals
907
908 if(loopZRR.dr.d_type == QType::SOA)
909 continue; // skip SOA - would indicate end of AXFR
910
911 if(csp.submit(loopZRR)) {
912 for(;;) {
913 outpacket->getRRS() = csp.getChunk();
914 if(!outpacket->getRRS().empty()) {
915 if(haveTSIGDetails && !tsigkeyname.empty())
916 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
917 sendPacket(outpacket, outsock);
918 trc.d_mac=outpacket->d_trc.d_mac;
919 outpacket=getFreshAXFRPacket(q);
920 }
921 else
922 break;
923 }
924 }
925 }
926 /*
927 udiff=dt.udiffNoReset();
928 cerr<<"Starting NSEC: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
929 cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
930 cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
931 */
932 if(securedZone) {
933 if(NSEC3Zone) {
934 for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
935 if(iter->second.d_auth) {
936 NSEC3RecordContent n3rc;
937 n3rc.set(iter->second.d_set);
938 const auto numberOfTypesSet = n3rc.numberOfTypesSet();
939 if (numberOfTypesSet != 0 && (numberOfTypesSet != 1 || !n3rc.isSet(QType::NS))) {
940 n3rc.set(QType::RRSIG);
941 }
942 n3rc.d_salt = ns3pr.d_salt;
943 n3rc.d_flags = ns3pr.d_flags;
944 n3rc.d_iterations = ns3pr.d_iterations;
945 n3rc.d_algorithm = DNSSECKeeper::SHA1; // SHA1, fixed in PowerDNS for now
946 nsecxrepo_t::const_iterator inext = iter;
947 ++inext;
948 if(inext == nsecxrepo.end())
949 inext = nsecxrepo.begin();
950 while(!inext->second.d_auth && inext != iter)
951 {
952 ++inext;
953 if(inext == nsecxrepo.end())
954 inext = nsecxrepo.begin();
955 }
956 n3rc.d_nexthash = fromBase32Hex(inext->first.toStringNoDot());
957 zrr.dr.d_name = iter->first+sd.qname;
958
959 zrr.dr.d_ttl = sd.default_ttl;
960 zrr.dr.d_content = std::make_shared<NSEC3RecordContent>(std::move(n3rc));
961 zrr.dr.d_type = QType::NSEC3;
962 zrr.dr.d_place = DNSResourceRecord::ANSWER;
963 zrr.auth=true;
964 if(csp.submit(zrr)) {
965 for(;;) {
966 outpacket->getRRS() = csp.getChunk();
967 if(!outpacket->getRRS().empty()) {
968 if(haveTSIGDetails && !tsigkeyname.empty())
969 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
970 sendPacket(outpacket, outsock);
971 trc.d_mac=outpacket->d_trc.d_mac;
972 outpacket=getFreshAXFRPacket(q);
973 }
974 else
975 break;
976 }
977 }
978 }
979 }
980 }
981 else for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
982 NSECRecordContent nrc;
983 nrc.set(iter->second.d_set);
984 nrc.set(QType::RRSIG);
985 nrc.set(QType::NSEC);
986
987 if(boost::next(iter) != nsecxrepo.end())
988 nrc.d_next = boost::next(iter)->first;
989 else
990 nrc.d_next=nsecxrepo.begin()->first;
991 zrr.dr.d_name = iter->first;
992
993 zrr.dr.d_ttl = sd.default_ttl;
994 zrr.dr.d_content = std::make_shared<NSECRecordContent>(std::move(nrc));
995 zrr.dr.d_type = QType::NSEC;
996 zrr.dr.d_place = DNSResourceRecord::ANSWER;
997 zrr.auth=true;
998 if(csp.submit(zrr)) {
999 for(;;) {
1000 outpacket->getRRS() = csp.getChunk();
1001 if(!outpacket->getRRS().empty()) {
1002 if(haveTSIGDetails && !tsigkeyname.empty())
1003 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
1004 sendPacket(outpacket, outsock);
1005 trc.d_mac=outpacket->d_trc.d_mac;
1006 outpacket=getFreshAXFRPacket(q);
1007 }
1008 else
1009 break;
1010 }
1011 }
1012 }
1013 }
1014 /*
1015 udiff=dt.udiffNoReset();
1016 cerr<<"Flushing pipe: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
1017 cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
1018 cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
1019 * */
1020 for(;;) {
1021 outpacket->getRRS() = csp.getChunk(true); // flush the pipe
1022 if(!outpacket->getRRS().empty()) {
1023 if(haveTSIGDetails && !tsigkeyname.empty())
1024 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); // first answer is 'normal'
1025 sendPacket(outpacket, outsock);
1026 trc.d_mac=outpacket->d_trc.d_mac;
1027 outpacket=getFreshAXFRPacket(q);
1028 }
1029 else
1030 break;
1031 }
1032
1033 udiff=dt.udiffNoReset();
1034 if(securedZone)
1035 g_log<<Logger::Info<<"Done signing: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<endl;
1036
1037 DLOG(g_log<<"Done writing out records"<<endl);
1038 /* and terminate with yet again the SOA record */
1039 outpacket=getFreshAXFRPacket(q);
1040 outpacket->addRecord(soa);
1041 if(haveTSIGDetails && !tsigkeyname.empty())
1042 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
1043
1044 sendPacket(outpacket, outsock);
1045
1046 DLOG(g_log<<"last packet - close"<<endl);
1047 g_log<<Logger::Error<<"AXFR of domain '"<<target<<"' to "<<q->getRemote()<<" finished"<<endl;
1048
1049 return 1;
1050 }
1051
1052 int TCPNameserver::doIXFR(shared_ptr<DNSPacket> q, int outsock)
1053 {
1054 shared_ptr<DNSPacket> outpacket=getFreshAXFRPacket(q);
1055 if(q->d_dnssecOk)
1056 outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
1057
1058 uint32_t serial = 0;
1059 MOADNSParser mdp(false, q->getString());
1060 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) {
1061 const DNSRecord *rr = &i->first;
1062 if (rr->d_type == QType::SOA && rr->d_place == DNSResourceRecord::AUTHORITY) {
1063 vector<string>parts;
1064 stringtok(parts, rr->d_content->getZoneRepresentation());
1065 if (parts.size() >= 3) {
1066 try {
1067 serial=pdns_stou(parts[2]);
1068 }
1069 catch(const std::out_of_range& oor) {
1070 g_log<<Logger::Error<<"Invalid serial in IXFR query"<<endl;
1071 outpacket->setRcode(RCode::FormErr);
1072 sendPacket(outpacket,outsock);
1073 return 0;
1074 }
1075 } else {
1076 g_log<<Logger::Error<<"No serial in IXFR query"<<endl;
1077 outpacket->setRcode(RCode::FormErr);
1078 sendPacket(outpacket,outsock);
1079 return 0;
1080 }
1081 } else if (rr->d_type != QType::TSIG && rr->d_type != QType::OPT) {
1082 g_log<<Logger::Error<<"Additional records in IXFR query, type: "<<QType(rr->d_type).getName()<<endl;
1083 outpacket->setRcode(RCode::FormErr);
1084 sendPacket(outpacket,outsock);
1085 return 0;
1086 }
1087 }
1088
1089 g_log<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' initiated by "<<q->getRemote()<<" with serial "<<serial<<endl;
1090
1091 // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
1092 SOAData sd;
1093 {
1094 Lock l(&s_plock);
1095 DLOG(g_log<<"Looking for SOA"<<endl); // find domain_id via SOA and list complete domain. No SOA, no IXFR
1096 if(!s_P) {
1097 g_log<<Logger::Error<<"TCP server is without backend connections in doIXFR, launching"<<endl;
1098 s_P=new PacketHandler;
1099 }
1100
1101 // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
1102 if(!canDoAXFR(q) || !s_P->getBackend()->getSOAUncached(q->qdomain, sd)) {
1103 g_log<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' failed: not authoritative"<<endl;
1104 outpacket->setRcode(RCode::NotAuth);
1105 sendPacket(outpacket,outsock);
1106 return 0;
1107 }
1108 }
1109
1110 DNSSECKeeper dk;
1111 NSEC3PARAMRecordContent ns3pr;
1112 bool narrow;
1113
1114 dk.clearCaches(q->qdomain);
1115 bool securedZone = dk.isSecuredZone(q->qdomain);
1116 if(dk.getNSEC3PARAM(q->qdomain, &ns3pr, &narrow)) {
1117 if(narrow) {
1118 g_log<<Logger::Error<<"Not doing IXFR of an NSEC3 narrow zone."<<endl;
1119 g_log<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' denied to "<<q->getRemote()<<endl;
1120 outpacket->setRcode(RCode::Refused);
1121 sendPacket(outpacket,outsock);
1122 return 0;
1123 }
1124 }
1125
1126 DNSName target = q->qdomain;
1127
1128 UeberBackend db;
1129 if(!db.getSOAUncached(target, sd)) {
1130 g_log<<Logger::Error<<"IXFR of domain '"<<target<<"' failed: not authoritative in second instance"<<endl;
1131 outpacket->setRcode(RCode::NotAuth);
1132 sendPacket(outpacket,outsock);
1133 return 0;
1134 }
1135
1136 if (!rfc1982LessThan(serial, calculateEditSOA(sd.serial, dk, sd.qname))) {
1137 TSIGRecordContent trc;
1138 DNSName tsigkeyname;
1139 string tsigsecret;
1140
1141 bool haveTSIGDetails = q->getTSIGDetails(&trc, &tsigkeyname);
1142
1143 if(haveTSIGDetails && !tsigkeyname.empty()) {
1144 string tsig64;
1145 DNSName algorithm=trc.d_algoName; // FIXME400: was toLowerCanonic, compare output
1146 if (algorithm == DNSName("hmac-md5.sig-alg.reg.int"))
1147 algorithm = DNSName("hmac-md5");
1148 Lock l(&s_plock);
1149 if(!s_P->getBackend()->getTSIGKey(tsigkeyname, &algorithm, &tsig64)) {
1150 g_log<<Logger::Error<<"TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"' not found"<<endl;
1151 return 0;
1152 }
1153 if (B64Decode(tsig64, tsigsecret) == -1) {
1154 g_log<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname<<"' for domain '"<<target<<"'"<<endl;
1155 return 0;
1156 }
1157 }
1158
1159 UeberBackend signatureDB;
1160
1161 // SOA *must* go out first, our signing pipe might reorder
1162 DLOG(g_log<<"Sending out SOA"<<endl);
1163 DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd);
1164 outpacket->addRecord(soa);
1165 if(securedZone) {
1166 set<DNSName> authSet;
1167 authSet.insert(target);
1168 addRRSigs(dk, signatureDB, authSet, outpacket->getRRS());
1169 }
1170
1171 if(haveTSIGDetails && !tsigkeyname.empty())
1172 outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal'
1173
1174 sendPacket(outpacket, outsock);
1175
1176 g_log<<Logger::Error<<"IXFR of domain '"<<target<<"' to "<<q->getRemote()<<" finished"<<endl;
1177
1178 return 1;
1179 }
1180
1181 g_log<<Logger::Error<<"IXFR fallback to AXFR for domain '"<<target<<"' our serial "<<sd.serial<<endl;
1182 return doAXFR(q->qdomain, q, outsock);
1183 }
1184
1185 TCPNameserver::~TCPNameserver()
1186 {
1187 delete d_connectionroom_sem;
1188 }
1189
1190 TCPNameserver::TCPNameserver()
1191 {
1192 d_maxTransactionsPerConn = ::arg().asNum("max-tcp-transactions-per-conn");
1193 d_idleTimeout = ::arg().asNum("tcp-idle-timeout");
1194 d_maxConnectionDuration = ::arg().asNum("max-tcp-connection-duration");
1195 d_maxConnectionsPerClient = ::arg().asNum("max-tcp-connections-per-client");
1196
1197 // sem_init(&d_connectionroom_sem,0,::arg().asNum("max-tcp-connections"));
1198 d_connectionroom_sem = new Semaphore( ::arg().asNum( "max-tcp-connections" ));
1199 d_maxTCPConnections = ::arg().asNum( "max-tcp-connections" );
1200 d_tid=0;
1201 vector<string>locals;
1202 stringtok(locals,::arg()["local-address"]," ,");
1203
1204 vector<string>locals6;
1205 stringtok(locals6,::arg()["local-ipv6"]," ,");
1206
1207 if(locals.empty() && locals6.empty())
1208 throw PDNSException("No local address specified");
1209
1210 d_ng.toMasks(::arg()["allow-axfr-ips"] );
1211
1212 signal(SIGPIPE,SIG_IGN);
1213
1214 for(vector<string>::const_iterator laddr=locals.begin();laddr!=locals.end();++laddr) {
1215 int s=socket(AF_INET,SOCK_STREAM,0);
1216
1217 if(s<0)
1218 throw PDNSException("Unable to acquire TCP socket: "+stringerror());
1219
1220 setCloseOnExec(s);
1221
1222 ComboAddress local(*laddr, ::arg().asNum("local-port"));
1223
1224 int tmp=1;
1225 if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
1226 g_log<<Logger::Error<<"Setsockopt failed"<<endl;
1227 _exit(1);
1228 }
1229
1230 if (::arg().asNum("tcp-fast-open") > 0) {
1231 #ifdef TCP_FASTOPEN
1232 int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
1233 if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
1234 g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<strerror(errno)<<endl;
1235 }
1236 #else
1237 g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
1238 #endif
1239 }
1240
1241 if( ::arg().mustDo("non-local-bind") )
1242 Utility::setBindAny(AF_INET, s);
1243
1244 if(::bind(s, (sockaddr*)&local, local.getSocklen())<0) {
1245 close(s);
1246 if( errno == EADDRNOTAVAIL && ! ::arg().mustDo("local-address-nonexist-fail") ) {
1247 g_log<<Logger::Error<<"IPv4 Address " << *laddr << " does not exist on this server - skipping TCP bind" << endl;
1248 continue;
1249 } else {
1250 g_log<<Logger::Error<<"Unable to bind to TCP socket " << *laddr << ": "<<strerror(errno)<<endl;
1251 throw PDNSException("Unable to bind to TCP socket");
1252 }
1253 }
1254
1255 listen(s,128);
1256 g_log<<Logger::Error<<"TCP server bound to "<<local.toStringWithPort()<<endl;
1257 d_sockets.push_back(s);
1258 struct pollfd pfd;
1259 memset(&pfd, 0, sizeof(pfd));
1260 pfd.fd = s;
1261 pfd.events = POLLIN;
1262
1263 d_prfds.push_back(pfd);
1264 }
1265
1266 for(vector<string>::const_iterator laddr=locals6.begin();laddr!=locals6.end();++laddr) {
1267 int s=socket(AF_INET6,SOCK_STREAM,0);
1268
1269 if(s<0)
1270 throw PDNSException("Unable to acquire TCPv6 socket: "+stringerror());
1271
1272 setCloseOnExec(s);
1273
1274 ComboAddress local(*laddr, ::arg().asNum("local-port"));
1275
1276 int tmp=1;
1277 if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
1278 g_log<<Logger::Error<<"Setsockopt failed"<<endl;
1279 _exit(1);
1280 }
1281
1282 if (::arg().asNum("tcp-fast-open") > 0) {
1283 #ifdef TCP_FASTOPEN
1284 int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
1285 if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
1286 g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<strerror(errno)<<endl;
1287 }
1288 #else
1289 g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
1290 #endif
1291 }
1292
1293 if( ::arg().mustDo("non-local-bind") )
1294 Utility::setBindAny(AF_INET6, s);
1295 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
1296 g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
1297 }
1298 if(bind(s, (const sockaddr*)&local, local.getSocklen())<0) {
1299 close(s);
1300 if( errno == 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 << ": "<<strerror(errno)<<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 g_log<<Logger::Error<<"TCP question accept error: "<<strerror(errno)<<endl;
1346
1347 if(errno==EMFILE) {
1348 g_log<<Logger::Error<<"TCP handler out of filedescriptors, exiting, won't recover from this"<<endl;
1349 _exit(1);
1350 }
1351 }
1352 else {
1353 if (d_maxConnectionsPerClient) {
1354 std::lock_guard<std::mutex> lock(s_clientsCountMutex);
1355 if (s_clientsCount[remote] >= d_maxConnectionsPerClient) {
1356 g_log<<Logger::Notice<<"Limit of simultaneous TCP connections per client reached for "<< remote<<", dropping"<<endl;
1357 close(fd);
1358 continue;
1359 }
1360 s_clientsCount[remote]++;
1361 }
1362
1363 pthread_t tid;
1364 d_connectionroom_sem->wait(); // blocks if no connections are available
1365
1366 int room;
1367 d_connectionroom_sem->getValue( &room);
1368 if(room<1)
1369 g_log<<Logger::Warning<<"Limit of simultaneous TCP connections reached - raise max-tcp-connections"<<endl;
1370
1371 if(pthread_create(&tid, 0, &doConnection, reinterpret_cast<void*>(fd))) {
1372 g_log<<Logger::Error<<"Error creating thread: "<<stringerror()<<endl;
1373 d_connectionroom_sem->post();
1374 close(fd);
1375 decrementClientCount(remote);
1376 }
1377 }
1378 }
1379 }
1380 }
1381 }
1382 catch(PDNSException &AE) {
1383 g_log<<Logger::Error<<"TCP Nameserver thread dying because of fatal error: "<<AE.reason<<endl;
1384 }
1385 catch(...) {
1386 g_log<<Logger::Error<<"TCPNameserver dying because of an unexpected fatal error"<<endl;
1387 }
1388 _exit(1); // take rest of server with us
1389 }
1390
1391
1392 unsigned int TCPNameserver::numTCPConnections()
1393 {
1394 int room;
1395 d_connectionroom_sem->getValue( &room);
1396 return d_maxTCPConnections - room;
1397 }