]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnspacket.cc
Merge remote-tracking branch 'origin/master' into api-tsig-keys
[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.getHeader()->tc=1;
323 }
324 goto noCommit;
325 }
326 }
327
328 // if(!pw.getHeader()->tc) // protect against double commit from addSignature
329
330 if(!d_rrs.empty()) pw.commit();
331
332 noCommit:;
333
334 if(d_haveednssubnet) {
335 EDNSSubnetOpts eso = d_eso;
336 eso.scope = Netmask(eso.source.getNetwork(), maxScopeMask);
337
338 string opt = makeEDNSSubnetOptsString(eso);
339 opts.push_back(make_pair(8, opt)); // 'EDNS SUBNET'
340 }
341
342 if(!opts.empty() || d_haveednssection || d_dnssecOk)
343 {
344 pw.addOpt(s_udpTruncationThreshold, d_ednsrcode, d_dnssecOk ? EDNSOpts::DNSSECOK : 0, opts);
345 pw.commit();
346 }
347 }
348 catch(std::exception& e) {
349 g_log<<Logger::Warning<<"Exception: "<<e.what()<<endl;
350 throw;
351 }
352 }
353
354 if(d_trc.d_algoName.countLabels())
355 addTSIG(pw, d_trc, d_tsigkeyname, d_tsigsecret, d_tsigprevious, d_tsigtimersonly);
356
357 d_rawpacket.assign((char*)&packet[0], packet.size()); // XXX we could do this natively on a vector..
358
359 // copy RR counts so they can be read later
360 d.qdcount = pw.getHeader()->qdcount;
361 d.ancount = pw.getHeader()->ancount;
362 d.nscount = pw.getHeader()->nscount;
363 d.arcount = pw.getHeader()->arcount;
364 }
365
366 void DNSPacket::setQuestion(int op, const DNSName &qd, int newqtype)
367 {
368 memset(&d,0,sizeof(d));
369 d.id=dns_random(0xffff);
370 d.rd=d.tc=d.aa=false;
371 d.qr=false;
372 d.qdcount=1; // is htons'ed later on
373 d.ancount=d.arcount=d.nscount=0;
374 d.opcode=op;
375 qdomain=qd;
376 qtype=newqtype;
377 }
378
379 /** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */
380 DNSPacket *DNSPacket::replyPacket() const
381 {
382 DNSPacket *r=new DNSPacket(false);
383 r->setSocket(d_socket);
384 r->d_anyLocal=d_anyLocal;
385 r->setRemote(&d_remote);
386 r->setAnswer(true); // this implies the allocation of the header
387 r->setA(true); // and we are authoritative
388 r->setRA(0); // no recursion available
389 r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it
390 r->setID(d.id);
391 r->setOpcode(d.opcode);
392
393 r->d_dt=d_dt;
394 r->d.qdcount=1;
395 r->d_tcp = d_tcp;
396 r->qdomain = qdomain;
397 r->qtype = qtype;
398 r->qclass = qclass;
399 r->d_maxreplylen = d_maxreplylen;
400 r->d_wantsnsid = d_wantsnsid;
401 r->d_dnssecOk = d_dnssecOk;
402 r->d_eso = d_eso;
403 r->d_haveednssubnet = d_haveednssubnet;
404 r->d_haveednssection = d_haveednssection;
405 r->d_ednsversion = 0;
406 r->d_ednsrcode = 0;
407
408 if(d_tsigkeyname.countLabels()) {
409 r->d_tsigkeyname = d_tsigkeyname;
410 r->d_tsigprevious = d_tsigprevious;
411 r->d_trc = d_trc;
412 r->d_tsigsecret = d_tsigsecret;
413 r->d_tsigtimersonly = d_tsigtimersonly;
414 }
415 r->d_havetsig = d_havetsig;
416 return r;
417 }
418
419 void DNSPacket::spoofQuestion(const DNSPacket *qd)
420 {
421 d_wrapped=true; // if we do this, don't later on wrapup
422
423 int labellen;
424 string::size_type i=sizeof(d);
425
426 for(;;) {
427 labellen = qd->d_rawpacket[i];
428 if(!labellen) break;
429 i++;
430 d_rawpacket.replace(i, labellen, qd->d_rawpacket, i, labellen);
431 i = i + labellen;
432 }
433 }
434
435 int DNSPacket::noparse(const char *mesg, size_t length)
436 {
437 d_rawpacket.assign(mesg,length);
438 if(length < 12) {
439 g_log << Logger::Debug << "Ignoring packet: too short ("<<length<<" < 12) from "
440 << d_remote.toStringWithPort()<< endl;
441 return -1;
442 }
443 d_wantsnsid=false;
444 d_maxreplylen=512;
445 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
446 return 0;
447 }
448
449 void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly)
450 {
451 d_trc=tr;
452 d_trc.d_origID = (((d.id & 0xFF)<<8) | ((d.id & 0xFF00)>>8));
453 d_tsigkeyname = keyname;
454 d_tsigsecret = secret;
455 d_tsigprevious = previous;
456 d_tsigtimersonly=timersonly;
457 }
458
459 bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_t* tsigPosOut) const
460 {
461 MOADNSParser mdp(d_isQuery, d_rawpacket);
462 uint16_t tsigPos = mdp.getTSIGPos();
463 if(!tsigPos)
464 return false;
465
466 bool gotit=false;
467 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
468 if(i->first.d_type == QType::TSIG && i->first.d_class == QType::ANY) {
469 // cast can fail, f.e. if d_content is an UnknownRecordContent.
470 shared_ptr<TSIGRecordContent> content = std::dynamic_pointer_cast<TSIGRecordContent>(i->first.d_content);
471 if (!content) {
472 g_log<<Logger::Error<<"TSIG record has no or invalid content (invalid packet)"<<endl;
473 return false;
474 }
475 *trc = *content;
476 *keyname = i->first.d_name;
477 gotit=true;
478 }
479 }
480 if(!gotit)
481 return false;
482
483 if (tsigPosOut) {
484 *tsigPosOut = tsigPos;
485 }
486
487 return true;
488 }
489
490 bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const
491 {
492 MOADNSParser mdp(d_isQuery, d_rawpacket);
493 bool gotit=false;
494
495 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
496 if (gotit) {
497 g_log<<Logger::Error<<"More than one TKEY record found in query"<<endl;
498 return false;
499 }
500
501 if(i->first.d_type == QType::TKEY) {
502 // cast can fail, f.e. if d_content is an UnknownRecordContent.
503 shared_ptr<TKEYRecordContent> content = std::dynamic_pointer_cast<TKEYRecordContent>(i->first.d_content);
504 if (!content) {
505 g_log<<Logger::Error<<"TKEY record has no or invalid content (invalid packet)"<<endl;
506 return false;
507 }
508 *tr = *content;
509 *keyname = i->first.d_name;
510 gotit=true;
511 }
512 }
513
514 return gotit;
515 }
516
517 /** This function takes data from the network, possibly received with recvfrom, and parses
518 it into our class. Results of calling this function multiple times on one packet are
519 unknown. Returns -1 if the packet cannot be parsed.
520 */
521 int DNSPacket::parse(const char *mesg, size_t length)
522 try
523 {
524 d_rawpacket.assign(mesg,length);
525 d_wrapped=true;
526 if(length < 12) {
527 g_log << Logger::Debug << "Ignoring packet: too short from "
528 << getRemote() << endl;
529 return -1;
530 }
531
532 MOADNSParser mdp(d_isQuery, d_rawpacket);
533 EDNSOpts edo;
534
535 // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST!
536
537 d_wantsnsid=false;
538 d_dnssecOk=false;
539 d_havetsig = mdp.getTSIGPos();
540 d_haveednssubnet = false;
541 d_haveednssection = false;
542
543 if(getEDNSOpts(mdp, &edo)) {
544 d_haveednssection=true;
545 /* rfc6891 6.2.3:
546 "Values lower than 512 MUST be treated as equal to 512."
547 */
548 d_ednsRawPacketSizeLimit=edo.d_packetsize;
549 d_maxreplylen=std::min(std::max(static_cast<uint16_t>(512), edo.d_packetsize), s_udpTruncationThreshold);
550 // cerr<<edo.d_extFlags<<endl;
551 if(edo.d_extFlags & EDNSOpts::DNSSECOK)
552 d_dnssecOk=true;
553
554 for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin();
555 iter != edo.d_options.end();
556 ++iter) {
557 if(iter->first == EDNSOptionCode::NSID) {
558 d_wantsnsid=true;
559 }
560 else if(s_doEDNSSubnetProcessing && (iter->first == EDNSOptionCode::ECS)) { // 'EDNS SUBNET'
561 if(getEDNSSubnetOptsFromString(iter->second, &d_eso)) {
562 //cerr<<"Parsed, source: "<<d_eso.source.toString()<<", scope: "<<d_eso.scope.toString()<<", family = "<<d_eso.scope.getNetwork().sin4.sin_family<<endl;
563 d_haveednssubnet=true;
564 }
565 }
566 else {
567 // cerr<<"Have an option #"<<iter->first<<": "<<makeHexDump(iter->second)<<endl;
568 }
569 }
570 d_ednsversion = edo.d_version;
571 d_ednsrcode = edo.d_extRCode;
572 }
573 else {
574 d_maxreplylen=512;
575 d_ednsRawPacketSizeLimit=-1;
576 }
577
578 memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12);
579 qdomain=mdp.d_qname;
580 // if(!qdomain.empty()) // strip dot
581 // boost::erase_tail(qdomain, 1);
582
583 if(!ntohs(d.qdcount)) {
584 if(!d_tcp) {
585 g_log << Logger::Warning << "No question section in packet from " << getRemote() <<", error="<<RCode::to_s(d.rcode)<<endl;
586 return -1;
587 }
588 }
589
590 qtype=mdp.d_qtype;
591 qclass=mdp.d_qclass;
592
593 d_trc = TSIGRecordContent();
594
595 return 0;
596 }
597 catch(std::exception& e) {
598 return -1;
599 }
600
601 unsigned int DNSPacket::getMaxReplyLen()
602 {
603 return d_maxreplylen;
604 }
605
606 void DNSPacket::setMaxReplyLen(int bytes)
607 {
608 d_maxreplylen=bytes;
609 }
610
611 //! Use this to set where this packet was received from or should be sent to
612 void DNSPacket::setRemote(const ComboAddress *s)
613 {
614 d_remote=*s;
615 }
616
617 bool DNSPacket::hasEDNSSubnet() const
618 {
619 return d_haveednssubnet;
620 }
621
622 bool DNSPacket::hasEDNS()
623 {
624 return d_haveednssection;
625 }
626
627 Netmask DNSPacket::getRealRemote() const
628 {
629 if(d_haveednssubnet)
630 return d_eso.source;
631 return Netmask(d_remote);
632 }
633
634 void DNSPacket::setSocket(Utility::sock_t sock)
635 {
636 d_socket=sock;
637 }
638
639 void DNSPacket::commitD()
640 {
641 d_rawpacket.replace(0,12,(char *)&d,12); // copy in d
642 }
643
644 bool DNSPacket::checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const
645 {
646 uint16_t tsigPos;
647
648 if (!this->getTSIGDetails(trc, keyname, &tsigPos)) {
649 return false;
650 }
651
652 TSIGTriplet tt;
653 tt.name = *keyname;
654 tt.algo = trc->d_algoName;
655 if (tt.algo == DNSName("hmac-md5.sig-alg.reg.int"))
656 tt.algo = DNSName("hmac-md5");
657
658 string secret64;
659 if (tt.algo != DNSName("gss-tsig")) {
660 if(!B->getTSIGKey(*keyname, &tt.algo, &secret64)) {
661 g_log<<Logger::Error<<"Packet for domain '"<<this->qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<<tt.algo<<"'"<<endl;
662 return false;
663 }
664 B64Decode(secret64, *secret);
665 tt.secret = *secret;
666 }
667
668 bool result;
669
670 try {
671 result = validateTSIG(d_rawpacket, tsigPos, tt, *trc, "", trc->d_mac, false);
672 }
673 catch(const std::runtime_error& err) {
674 g_log<<Logger::Error<<"Packet for '"<<this->qdomain<<"' denied: "<<err.what()<<endl;
675 return false;
676 }
677
678 return result;
679 }
680
681 const DNSName& DNSPacket::getTSIGKeyname() const {
682 return d_tsigkeyname;
683 }