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