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