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