]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnspacket.cc
Avoid throwing an exception in Logger::log().
[thirdparty/pdns.git] / pdns / dnspacket.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "utility.hh"
26 #include <cstdio>
27 #include <cstdlib>
28 #include <sys/types.h>
29 #include <iostream>
30 #include <string>
31 #include <boost/tokenizer.hpp>
32 #include <boost/functional/hash.hpp>
33 #include <boost/algorithm/string.hpp>
34 #include <openssl/hmac.h>
35 #include <algorithm>
36
37 #include "dnsseckeeper.hh"
38 #include "dns.hh"
39 #include "dnsbackend.hh"
40 #include "ednsoptions.hh"
41 #include "pdnsexception.hh"
42 #include "dnspacket.hh"
43 #include "logger.hh"
44 #include "arguments.hh"
45 #include "dnswriter.hh"
46 #include "dnsparser.hh"
47 #include "dnsrecords.hh"
48 #include "dnssecinfra.hh"
49 #include "base64.hh"
50 #include "ednssubnet.hh"
51 #include "gss_context.hh"
52 #include "dns_random.hh"
53 #include "shuffle.hh"
54
55 bool DNSPacket::s_doEDNSSubnetProcessing;
56 uint16_t DNSPacket::s_udpTruncationThreshold;
57
58 DNSPacket::DNSPacket(bool isQuery): d_isQuery(isQuery)
59 {
60 memset(&d, 0, sizeof(d));
61 }
62
63 const string& DNSPacket::getString()
64 {
65 if(!d_wrapped)
66 wrapup();
67
68 return d_rawpacket;
69 }
70
71 ComboAddress DNSPacket::getRemote() const
72 {
73 return d_remote;
74 }
75
76 uint16_t DNSPacket::getRemotePort() const
77 {
78 return d_remote.sin4.sin_port;
79 }
80
81 void DNSPacket::setRcode(int v)
82 {
83 d.rcode=v;
84 }
85
86 void DNSPacket::setAnswer(bool b)
87 {
88 if(b) {
89 d_rawpacket.assign(12,(char)0);
90 memset((void *)&d,0,sizeof(d));
91
92 d.qr=b;
93 }
94 }
95
96 void DNSPacket::setA(bool b)
97 {
98 d.aa=b;
99 }
100
101 void DNSPacket::setID(uint16_t id)
102 {
103 d.id=id;
104 }
105
106 void DNSPacket::setRA(bool b)
107 {
108 d.ra=b;
109 }
110
111 void DNSPacket::setRD(bool b)
112 {
113 d.rd=b;
114 }
115
116 void DNSPacket::setOpcode(uint16_t opcode)
117 {
118 d.opcode=opcode;
119 }
120
121 void DNSPacket::clearRecords()
122 {
123 d_rrs.clear();
124 d_dedup.clear();
125 }
126
127 void DNSPacket::addRecord(DNSZoneRecord&& rr)
128 {
129 // this removes duplicates from the packet.
130 // in case we are not compressing for AXFR, no such checking is performed!
131
132 if(d_compress) {
133 std::string ser = const_cast<DNSZoneRecord&>(rr).dr.d_content->serialize(rr.dr.d_name);
134 auto hash = boost::hash< std::pair<DNSName, std::string> >()({rr.dr.d_name, ser});
135 if(d_dedup.count(hash)) { // might be a dup
136 for(auto i=d_rrs.begin();i!=d_rrs.end();++i) {
137 if(rr.dr == i->dr) // XXX SUPER SLOW
138 return;
139 }
140 }
141 d_dedup.insert(hash);
142 }
143
144 d_rrs.push_back(std::move(rr));
145 }
146
147 vector<DNSZoneRecord*> DNSPacket::getAPRecords()
148 {
149 vector<DNSZoneRecord*> arrs;
150
151 for(vector<DNSZoneRecord>::iterator i=d_rrs.begin();
152 i!=d_rrs.end();
153 ++i)
154 {
155 if(i->dr.d_place!=DNSResourceRecord::ADDITIONAL &&
156 (i->dr.d_type==QType::MX ||
157 i->dr.d_type==QType::NS ||
158 i->dr.d_type==QType::SRV))
159 {
160 arrs.push_back(&*i);
161 }
162 }
163 return arrs;
164 }
165
166 vector<DNSZoneRecord*> DNSPacket::getAnswerRecords()
167 {
168 vector<DNSZoneRecord*> arrs;
169
170 for(vector<DNSZoneRecord>::iterator i=d_rrs.begin();
171 i!=d_rrs.end();
172 ++i)
173 {
174 if(i->dr.d_place!=DNSResourceRecord::ADDITIONAL)
175 arrs.push_back(&*i);
176 }
177 return arrs;
178 }
179
180
181 void DNSPacket::setCompress(bool compress)
182 {
183 d_compress=compress;
184 d_rawpacket.reserve(65000);
185 d_rrs.reserve(200);
186 }
187
188 bool DNSPacket::couldBeCached() const
189 {
190 return !d_wantsnsid && qclass==QClass::IN && !d_havetsig;
191 }
192
193 unsigned int DNSPacket::getMinTTL()
194 {
195 unsigned int minttl = UINT_MAX;
196 for(const DNSZoneRecord& rr : d_rrs) {
197 if (rr.dr.d_ttl < minttl)
198 minttl = rr.dr.d_ttl;
199 }
200
201 return minttl;
202 }
203
204 bool DNSPacket::isEmpty()
205 {
206 return (d_rrs.empty());
207 }
208
209 /** Must be called before attempting to access getData(). This function stuffs all resource
210 * records found in rrs into the data buffer. It also frees resource records queued for us.
211 */
212 void DNSPacket::wrapup()
213 {
214 if(d_wrapped) {
215 return;
216 }
217
218 DNSZoneRecord rr;
219 vector<DNSZoneRecord>::iterator pos;
220
221 // we now need to order rrs so that the different sections come at the right place
222 // we want a stable sort, based on the d_place field
223
224 stable_sort(d_rrs.begin(),d_rrs.end(), [](const DNSZoneRecord& a, const DNSZoneRecord& b) {
225 return a.dr.d_place < b.dr.d_place;
226 });
227 static bool mustNotShuffle = ::arg().mustDo("no-shuffle");
228
229 if(!d_tcp && !mustNotShuffle) {
230 pdns::shuffle(d_rrs);
231 }
232 d_wrapped=true;
233
234 vector<uint8_t> packet;
235 DNSPacketWriter pw(packet, qdomain, qtype.getCode(), qclass);
236
237 pw.getHeader()->rcode=d.rcode;
238 pw.getHeader()->opcode = d.opcode;
239 pw.getHeader()->aa=d.aa;
240 pw.getHeader()->ra=d.ra;
241 pw.getHeader()->qr=d.qr;
242 pw.getHeader()->id=d.id;
243 pw.getHeader()->rd=d.rd;
244 pw.getHeader()->tc=d.tc;
245
246 DNSPacketWriter::optvect_t opts;
247
248 /* optsize is expected to hold an upper bound of data that will be
249 added after actual record data - i.e. OPT, TSIG, perhaps one day
250 XPF. Because of the way `pw` incrementally writes the packet, we
251 cannot easily 'go back' and remove a few records. So, to prevent
252 going over our maximum size, we keep our (potential) extra data
253 in mind.
254
255 This means that sometimes we'll send TC even if we'd end up with
256 a few bytes to spare, but so be it.
257 */
258 size_t optsize = 0;
259
260 if (d_haveednssection || d_dnssecOk) {
261 /* root label (1), type (2), class (2), ttl (4) + rdlen (2) */
262 optsize = 11;
263 }
264
265 if(d_wantsnsid) {
266 const static string mode_server_id=::arg()["server-id"];
267 if(mode_server_id != "disabled") {
268 opts.push_back(make_pair(EDNSOptionCode::NSID, mode_server_id));
269 optsize += EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + mode_server_id.size();
270 }
271 }
272
273 if (d_haveednssubnet)
274 {
275 // this is an upper bound
276 optsize += EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + 2 + 1 + 1; // code+len+family+src len+scope len
277 optsize += d_eso.source.isIPv4() ? 4 : 16;
278 }
279
280 if (d_trc.d_algoName.countLabels())
281 {
282 // TSIG is not OPT, but we count it in optsize anyway
283 optsize += d_trc.d_algoName.wirelength() + 3 + 1 + 2; // algo + time + fudge + maclen
284 optsize += EVP_MAX_MD_SIZE + 2 + 2 + 2 + 0; // mac + origid + ercode + otherdatalen + no other data
285
286 static_assert(EVP_MAX_MD_SIZE <= 64, "EVP_MAX_MD_SIZE is overly huge on this system, please check");
287 }
288
289 if(!d_rrs.empty() || !opts.empty() || d_haveednssubnet || d_haveednssection) {
290 try {
291 uint8_t maxScopeMask=0;
292 for(pos=d_rrs.begin(); pos < d_rrs.end(); ++pos) {
293 // cerr<<"during wrapup, content=["<<pos->content<<"]"<<endl;
294 maxScopeMask = max(maxScopeMask, pos->scopeMask);
295
296 pw.startRecord(pos->dr.d_name, pos->dr.d_type, pos->dr.d_ttl, pos->dr.d_class, pos->dr.d_place);
297 pos->dr.d_content->toPacket(pw);
298 if(pw.size() + optsize > (d_tcp ? 65535 : getMaxReplyLen())) {
299 pw.rollback();
300 pw.truncate();
301 pw.getHeader()->tc=1;
302 goto noCommit;
303 }
304 }
305
306 // if(!pw.getHeader()->tc) // protect against double commit from addSignature
307
308 if(!d_rrs.empty()) pw.commit();
309
310 noCommit:;
311
312 if(d_haveednssubnet) {
313 EDNSSubnetOpts eso = d_eso;
314 eso.scope = Netmask(eso.source.getNetwork(), maxScopeMask);
315
316 string opt = makeEDNSSubnetOptsString(eso);
317 opts.push_back(make_pair(8, opt)); // 'EDNS SUBNET'
318 }
319
320 if(!opts.empty() || d_haveednssection || d_dnssecOk)
321 {
322 pw.addOpt(s_udpTruncationThreshold, d_ednsrcode, d_dnssecOk ? EDNSOpts::DNSSECOK : 0, opts);
323 pw.commit();
324 }
325 }
326 catch(std::exception& e) {
327 g_log<<Logger::Warning<<"Exception: "<<e.what()<<endl;
328 throw;
329 }
330 }
331
332 if(d_trc.d_algoName.countLabels())
333 addTSIG(pw, d_trc, d_tsigkeyname, d_tsigsecret, d_tsigprevious, d_tsigtimersonly);
334
335 d_rawpacket.assign((char*)&packet[0], packet.size()); // XXX we could do this natively on a vector..
336
337 // copy RR counts so they can be read later
338 d.qdcount = pw.getHeader()->qdcount;
339 d.ancount = pw.getHeader()->ancount;
340 d.nscount = pw.getHeader()->nscount;
341 d.arcount = pw.getHeader()->arcount;
342 }
343
344 void DNSPacket::setQuestion(int op, const DNSName &qd, int newqtype)
345 {
346 memset(&d,0,sizeof(d));
347 d.id=dns_random_uint16();
348 d.rd=d.tc=d.aa=false;
349 d.qr=false;
350 d.qdcount=1; // is htons'ed later on
351 d.ancount=d.arcount=d.nscount=0;
352 d.opcode=op;
353 qdomain=qd;
354 qtype=newqtype;
355 }
356
357 /** convenience function for creating a reply packet from a question packet. */
358 std::unique_ptr<DNSPacket> DNSPacket::replyPacket() const
359 {
360 auto r=make_unique<DNSPacket>(false);
361 r->setSocket(d_socket);
362 r->d_anyLocal=d_anyLocal;
363 r->setRemote(&d_remote);
364 r->setAnswer(true); // this implies the allocation of the header
365 r->setA(true); // and we are authoritative
366 r->setRA(0); // no recursion available
367 r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it
368 r->setID(d.id);
369 r->setOpcode(d.opcode);
370
371 r->d_dt=d_dt;
372 r->d.qdcount=1;
373 r->d_tcp = d_tcp;
374 r->qdomain = qdomain;
375 r->qtype = qtype;
376 r->qclass = qclass;
377 r->d_maxreplylen = d_maxreplylen;
378 r->d_wantsnsid = d_wantsnsid;
379 r->d_dnssecOk = d_dnssecOk;
380 r->d_eso = d_eso;
381 r->d_haveednssubnet = d_haveednssubnet;
382 r->d_haveednssection = d_haveednssection;
383 r->d_ednsversion = 0;
384 r->d_ednsrcode = 0;
385
386 if(d_tsigkeyname.countLabels()) {
387 r->d_tsigkeyname = d_tsigkeyname;
388 r->d_tsigprevious = d_tsigprevious;
389 r->d_trc = d_trc;
390 r->d_tsigsecret = d_tsigsecret;
391 r->d_tsigtimersonly = d_tsigtimersonly;
392 }
393 r->d_havetsig = d_havetsig;
394 return r;
395 }
396
397 void DNSPacket::spoofQuestion(const DNSPacket& qd)
398 {
399 d_wrapped=true; // if we do this, don't later on wrapup
400
401 int labellen;
402 string::size_type i=sizeof(d);
403
404 for(;;) {
405 labellen = qd.d_rawpacket[i];
406 if(!labellen) break;
407 i++;
408 d_rawpacket.replace(i, labellen, qd.d_rawpacket, i, labellen);
409 i = i + labellen;
410 }
411 }
412
413 int DNSPacket::noparse(const char *mesg, size_t length)
414 {
415 d_rawpacket.assign(mesg,length);
416 if(length < 12) {
417 g_log << Logger::Debug << "Ignoring packet: too short ("<<length<<" < 12) from "
418 << d_remote.toStringWithPort()<< endl;
419 return -1;
420 }
421 d_wantsnsid=false;
422 d_maxreplylen=512;
423 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
424 return 0;
425 }
426
427 void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly)
428 {
429 d_trc=tr;
430 d_trc.d_origID = (((d.id & 0xFF)<<8) | ((d.id & 0xFF00)>>8));
431 d_tsigkeyname = keyname;
432 d_tsigsecret = secret;
433 d_tsigprevious = previous;
434 d_tsigtimersonly=timersonly;
435 }
436
437 bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_t* tsigPosOut) const
438 {
439 MOADNSParser mdp(d_isQuery, d_rawpacket);
440 uint16_t tsigPos = mdp.getTSIGPos();
441 if(!tsigPos)
442 return false;
443
444 bool gotit=false;
445 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
446 if(i->first.d_type == QType::TSIG && i->first.d_class == QType::ANY) {
447 // cast can fail, f.e. if d_content is an UnknownRecordContent.
448 shared_ptr<TSIGRecordContent> content = std::dynamic_pointer_cast<TSIGRecordContent>(i->first.d_content);
449 if (!content) {
450 g_log<<Logger::Error<<"TSIG record has no or invalid content (invalid packet)"<<endl;
451 return false;
452 }
453 *trc = *content;
454 *keyname = i->first.d_name;
455 gotit=true;
456 }
457 }
458 if(!gotit)
459 return false;
460
461 if (tsigPosOut) {
462 *tsigPosOut = tsigPos;
463 }
464
465 return true;
466 }
467
468 bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const
469 {
470 MOADNSParser mdp(d_isQuery, d_rawpacket);
471 bool gotit=false;
472
473 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
474 if (gotit) {
475 g_log<<Logger::Error<<"More than one TKEY record found in query"<<endl;
476 return false;
477 }
478
479 if(i->first.d_type == QType::TKEY) {
480 // cast can fail, f.e. if d_content is an UnknownRecordContent.
481 shared_ptr<TKEYRecordContent> content = std::dynamic_pointer_cast<TKEYRecordContent>(i->first.d_content);
482 if (!content) {
483 g_log<<Logger::Error<<"TKEY record has no or invalid content (invalid packet)"<<endl;
484 return false;
485 }
486 *tr = *content;
487 *keyname = i->first.d_name;
488 gotit=true;
489 }
490 }
491
492 return gotit;
493 }
494
495 /** This function takes data from the network, possibly received with recvfrom, and parses
496 it into our class. Results of calling this function multiple times on one packet are
497 unknown. Returns -1 if the packet cannot be parsed.
498 */
499 int DNSPacket::parse(const char *mesg, size_t length)
500 try
501 {
502 d_rawpacket.assign(mesg,length);
503 d_wrapped=true;
504 if(length < 12) {
505 g_log << Logger::Debug << "Ignoring packet: too short from "
506 << getRemote() << endl;
507 return -1;
508 }
509
510 MOADNSParser mdp(d_isQuery, d_rawpacket);
511 EDNSOpts edo;
512
513 // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST!
514
515 d_wantsnsid=false;
516 d_dnssecOk=false;
517 d_havetsig = mdp.getTSIGPos();
518 d_haveednssubnet = false;
519 d_haveednssection = false;
520
521 if(getEDNSOpts(mdp, &edo)) {
522 d_haveednssection=true;
523 /* rfc6891 6.2.3:
524 "Values lower than 512 MUST be treated as equal to 512."
525 */
526 d_ednsRawPacketSizeLimit=edo.d_packetsize;
527 d_maxreplylen=std::min(std::max(static_cast<uint16_t>(512), edo.d_packetsize), s_udpTruncationThreshold);
528 // cerr<<edo.d_extFlags<<endl;
529 if(edo.d_extFlags & EDNSOpts::DNSSECOK)
530 d_dnssecOk=true;
531
532 for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin();
533 iter != edo.d_options.end();
534 ++iter) {
535 if(iter->first == EDNSOptionCode::NSID) {
536 d_wantsnsid=true;
537 }
538 else if(s_doEDNSSubnetProcessing && (iter->first == EDNSOptionCode::ECS)) { // 'EDNS SUBNET'
539 if(getEDNSSubnetOptsFromString(iter->second, &d_eso)) {
540 //cerr<<"Parsed, source: "<<d_eso.source.toString()<<", scope: "<<d_eso.scope.toString()<<", family = "<<d_eso.scope.getNetwork().sin4.sin_family<<endl;
541 d_haveednssubnet=true;
542 }
543 }
544 else {
545 // cerr<<"Have an option #"<<iter->first<<": "<<makeHexDump(iter->second)<<endl;
546 }
547 }
548 d_ednsversion = edo.d_version;
549 d_ednsrcode = edo.d_extRCode;
550 }
551 else {
552 d_maxreplylen=512;
553 d_ednsRawPacketSizeLimit=-1;
554 }
555
556 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
557 qdomain=mdp.d_qname;
558 // if(!qdomain.empty()) // strip dot
559 // boost::erase_tail(qdomain, 1);
560
561 if(!ntohs(d.qdcount)) {
562 if(!d_tcp) {
563 g_log << Logger::Debug << "No question section in packet from " << getRemote() <<", RCode="<<RCode::to_s(d.rcode)<<endl;
564 return -1;
565 }
566 }
567
568 qtype=mdp.d_qtype;
569 qclass=mdp.d_qclass;
570
571 d_trc = TSIGRecordContent();
572
573 return 0;
574 }
575 catch(std::exception& e) {
576 return -1;
577 }
578
579 unsigned int DNSPacket::getMaxReplyLen()
580 {
581 return d_maxreplylen;
582 }
583
584 void DNSPacket::setMaxReplyLen(int bytes)
585 {
586 d_maxreplylen=bytes;
587 }
588
589 //! Use this to set where this packet was received from or should be sent to
590 void DNSPacket::setRemote(const ComboAddress *s)
591 {
592 d_remote=*s;
593 }
594
595 bool DNSPacket::hasEDNSSubnet() const
596 {
597 return d_haveednssubnet;
598 }
599
600 bool DNSPacket::hasEDNS() const
601 {
602 return d_haveednssection;
603 }
604
605 Netmask DNSPacket::getRealRemote() const
606 {
607 if(d_haveednssubnet)
608 return d_eso.source;
609 return Netmask(d_remote);
610 }
611
612 void DNSPacket::setSocket(Utility::sock_t sock)
613 {
614 d_socket=sock;
615 }
616
617 void DNSPacket::commitD()
618 {
619 d_rawpacket.replace(0,12,(char *)&d,12); // copy in d
620 }
621
622 bool DNSPacket::checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const
623 {
624 uint16_t tsigPos;
625
626 if (!this->getTSIGDetails(trc, keyname, &tsigPos)) {
627 return false;
628 }
629
630 TSIGTriplet tt;
631 tt.name = *keyname;
632 tt.algo = trc->d_algoName;
633 if (tt.algo == DNSName("hmac-md5.sig-alg.reg.int"))
634 tt.algo = DNSName("hmac-md5");
635
636 string secret64;
637 if (tt.algo != DNSName("gss-tsig")) {
638 if(!B->getTSIGKey(*keyname, &tt.algo, &secret64)) {
639 g_log<<Logger::Error<<"Packet for domain '"<<this->qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<<tt.algo<<"'"<<endl;
640 return false;
641 }
642 B64Decode(secret64, *secret);
643 tt.secret = *secret;
644 }
645
646 bool result;
647
648 try {
649 result = validateTSIG(d_rawpacket, tsigPos, tt, *trc, "", trc->d_mac, false);
650 }
651 catch(const std::runtime_error& err) {
652 g_log<<Logger::Error<<"Packet for '"<<this->qdomain<<"' denied: "<<err.what()<<endl;
653 return false;
654 }
655
656 return result;
657 }
658
659 const DNSName& DNSPacket::getTSIGKeyname() const {
660 return d_tsigkeyname;
661 }