]>
Commit | Line | Data |
---|---|---|
12c86877 BH |
1 | /* |
2 | PowerDNS Versatile Database Driven Nameserver | |
213cc78f | 3 | Copyright (C) 2001 - 2011 PowerDNS.COM BV |
12c86877 BH |
4 | |
5 | This program is free software; you can redistribute it and/or modify | |
feccc9fc | 6 | it under the terms of the GNU General Public License version 2 as |
f28307ad | 7 | published by the Free Software Foundation |
12c86877 BH |
8 | |
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with this program; if not, write to the Free Software | |
06bd9ccf | 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
12c86877 | 17 | */ |
ff6a1e7b | 18 | |
12c86877 BH |
19 | #include "utility.hh" |
20 | #include <cstdio> | |
21 | ||
22 | #include <cstdlib> | |
23 | #include <sys/types.h> | |
24 | ||
25 | #include <iostream> | |
26 | ||
27 | #include <string> | |
28 | #include <errno.h> | |
b8e0f341 BH |
29 | #include <boost/tokenizer.hpp> |
30 | #include <boost/algorithm/string.hpp> | |
12c86877 | 31 | #include <algorithm> |
9c92ad4b BH |
32 | #include <boost/foreach.hpp> |
33 | #include "dnsseckeeper.hh" | |
12c86877 BH |
34 | #include "dns.hh" |
35 | #include "dnsbackend.hh" | |
36 | #include "ahuexception.hh" | |
37 | #include "dnspacket.hh" | |
38 | #include "logger.hh" | |
39 | #include "arguments.hh" | |
b8e0f341 BH |
40 | #include "dnswriter.hh" |
41 | #include "dnsparser.hh" | |
7f7b8d55 | 42 | #include "dnsrecords.hh" |
9c92ad4b | 43 | #include "dnssecinfra.hh" |
20665beb | 44 | #include "base64.hh" |
12c86877 BH |
45 | |
46 | DNSPacket::DNSPacket() | |
47 | { | |
48 | d_wrapped=false; | |
49 | d_compress=true; | |
e9dd48f9 | 50 | d_tcp=false; |
7f7b8d55 | 51 | d_wantsnsid=false; |
9c92ad4b | 52 | d_dnssecOk=false; |
12c86877 BH |
53 | } |
54 | ||
78bcb858 | 55 | const string& DNSPacket::getString() |
b8e0f341 BH |
56 | { |
57 | if(!d_wrapped) | |
e02d0a59 | 58 | wrapup(); |
b8e0f341 | 59 | |
78bcb858 | 60 | return d_rawpacket; |
b8e0f341 BH |
61 | } |
62 | ||
12c86877 BH |
63 | string DNSPacket::getRemote() const |
64 | { | |
d06799d4 | 65 | return d_remote.toString(); |
12c86877 BH |
66 | } |
67 | ||
092f210a | 68 | uint16_t DNSPacket::getRemotePort() const |
288f4aa9 | 69 | { |
d06799d4 | 70 | return d_remote.sin4.sin_port; |
288f4aa9 | 71 | } |
12c86877 | 72 | |
12c86877 BH |
73 | DNSPacket::DNSPacket(const DNSPacket &orig) |
74 | { | |
75 | DLOG(L<<"DNSPacket copy constructor called!"<<endl); | |
76 | d_socket=orig.d_socket; | |
d06799d4 | 77 | d_remote=orig.d_remote; |
12c86877 BH |
78 | d_qlen=orig.d_qlen; |
79 | d_dt=orig.d_dt; | |
12c86877 | 80 | d_compress=orig.d_compress; |
f28307ad | 81 | d_tcp=orig.d_tcp; |
12c86877 BH |
82 | qtype=orig.qtype; |
83 | qclass=orig.qclass; | |
84 | qdomain=orig.qdomain; | |
657e9124 | 85 | d_maxreplylen = orig.d_maxreplylen; |
7f7b8d55 BH |
86 | d_ednsping = orig.d_ednsping; |
87 | d_wantsnsid = orig.d_wantsnsid; | |
9c92ad4b BH |
88 | d_dnssecOk = orig.d_dnssecOk; |
89 | d_rrs=orig.d_rrs; | |
78bcb858 BH |
90 | |
91 | d_tsigkeyname = orig.d_tsigkeyname; | |
92 | d_tsigprevious = orig.d_tsigprevious; | |
93 | d_tsigtimersonly = orig.d_tsigtimersonly; | |
94 | d_trc = orig.d_trc; | |
95 | d_tsigsecret = orig.d_tsigsecret; | |
96 | ||
6dc26cf0 | 97 | d_havetsig = orig.d_havetsig; |
12c86877 BH |
98 | d_wrapped=orig.d_wrapped; |
99 | ||
78bcb858 | 100 | d_rawpacket=orig.d_rawpacket; |
12c86877 | 101 | d=orig.d; |
12c86877 BH |
102 | } |
103 | ||
12c86877 BH |
104 | void DNSPacket::setRcode(int v) |
105 | { | |
106 | d.rcode=v; | |
107 | } | |
108 | ||
109 | void DNSPacket::setAnswer(bool b) | |
110 | { | |
111 | if(b) { | |
78bcb858 | 112 | d_rawpacket.assign(12,(char)0); |
12c86877 BH |
113 | memset((void *)&d,0,sizeof(d)); |
114 | ||
115 | d.qr=b; | |
116 | } | |
117 | } | |
118 | ||
119 | void DNSPacket::setA(bool b) | |
120 | { | |
121 | d.aa=b; | |
122 | } | |
123 | ||
092f210a | 124 | void DNSPacket::setID(uint16_t id) |
12c86877 BH |
125 | { |
126 | d.id=id; | |
127 | } | |
128 | ||
129 | void DNSPacket::setRA(bool b) | |
130 | { | |
131 | d.ra=b; | |
132 | } | |
133 | ||
134 | void DNSPacket::setRD(bool b) | |
135 | { | |
136 | d.rd=b; | |
137 | } | |
138 | ||
092f210a | 139 | void DNSPacket::setOpcode(uint16_t opcode) |
12c86877 BH |
140 | { |
141 | d.opcode=opcode; | |
142 | } | |
143 | ||
12c86877 | 144 | |
77235722 BH |
145 | void DNSPacket::clearRecords() |
146 | { | |
9c92ad4b | 147 | d_rrs.clear(); |
77235722 BH |
148 | } |
149 | ||
12c86877 BH |
150 | void DNSPacket::addRecord(const DNSResourceRecord &rr) |
151 | { | |
152 | if(d_compress) | |
9c92ad4b | 153 | for(vector<DNSResourceRecord>::const_iterator i=d_rrs.begin();i!=d_rrs.end();++i) |
ab2249ae | 154 | if(rr.qname==i->qname && rr.qtype==i->qtype && rr.content==i->content) { |
4957a608 BH |
155 | if(rr.qtype.getCode()!=QType::MX && rr.qtype.getCode()!=QType::SRV) |
156 | return; | |
157 | if(rr.priority==i->priority) | |
158 | return; | |
ab2249ae | 159 | } |
12c86877 | 160 | |
9c92ad4b | 161 | d_rrs.push_back(rr); |
12c86877 BH |
162 | } |
163 | ||
12c86877 | 164 | |
12c86877 BH |
165 | |
166 | static int rrcomp(const DNSResourceRecord &A, const DNSResourceRecord &B) | |
167 | { | |
e02d0a59 | 168 | if(A.d_place < B.d_place) |
12c86877 BH |
169 | return 1; |
170 | ||
171 | return 0; | |
172 | } | |
173 | ||
f6ba332a | 174 | vector<DNSResourceRecord*> DNSPacket::getAPRecords() |
12c86877 | 175 | { |
f6ba332a | 176 | vector<DNSResourceRecord*> arrs; |
12c86877 | 177 | |
9c92ad4b BH |
178 | for(vector<DNSResourceRecord>::iterator i=d_rrs.begin(); |
179 | i!=d_rrs.end(); | |
12c86877 BH |
180 | ++i) |
181 | { | |
182 | if(i->d_place!=DNSResourceRecord::ADDITIONAL && | |
4957a608 BH |
183 | (i->qtype.getCode()==15 || |
184 | i->qtype.getCode()==2 )) // CNAME or MX or NS | |
185 | { | |
186 | arrs.push_back(&*i); | |
187 | } | |
12c86877 BH |
188 | } |
189 | ||
190 | return arrs; | |
191 | ||
192 | } | |
193 | ||
9c92ad4b BH |
194 | vector<DNSResourceRecord*> DNSPacket::getAnswerRecords() |
195 | { | |
196 | vector<DNSResourceRecord*> arrs; | |
197 | ||
198 | for(vector<DNSResourceRecord>::iterator i=d_rrs.begin(); | |
199 | i!=d_rrs.end(); | |
200 | ++i) | |
201 | { | |
202 | if(i->d_place!=DNSResourceRecord::ADDITIONAL) | |
203 | arrs.push_back(&*i); | |
204 | } | |
205 | return arrs; | |
206 | } | |
207 | ||
208 | ||
12c86877 BH |
209 | void DNSPacket::setCompress(bool compress) |
210 | { | |
211 | d_compress=compress; | |
78bcb858 | 212 | d_rawpacket.reserve(65000); |
9c92ad4b | 213 | d_rrs.reserve(200); |
12c86877 BH |
214 | } |
215 | ||
7f7b8d55 BH |
216 | bool DNSPacket::couldBeCached() |
217 | { | |
adf13442 | 218 | return d_ednsping.empty() && !d_wantsnsid && qclass==QClass::IN; |
7f7b8d55 | 219 | } |
20665beb | 220 | |
12c86877 BH |
221 | /** Must be called before attempting to access getData(). This function stuffs all resource |
222 | * records found in rrs into the data buffer. It also frees resource records queued for us. | |
223 | */ | |
e02d0a59 | 224 | void DNSPacket::wrapup() |
12c86877 BH |
225 | { |
226 | if(d_wrapped) { | |
227 | return; | |
228 | } | |
51a3a4d4 | 229 | |
12c86877 BH |
230 | DNSResourceRecord rr; |
231 | vector<DNSResourceRecord>::iterator pos; | |
232 | ||
12c86877 BH |
233 | // we now need to order rrs so that the different sections come at the right place |
234 | // we want a stable sort, based on the d_place field | |
235 | ||
e02d0a59 | 236 | stable_sort(d_rrs.begin(),d_rrs.end(), rrcomp); |
4c5d6da9 | 237 | static bool mustNotShuffle = ::arg().mustDo("no-shuffle"); |
da73ef3c | 238 | |
4c5d6da9 | 239 | if(!d_tcp && !mustNotShuffle) { |
9c92ad4b | 240 | shuffle(d_rrs); |
ff6a1e7b | 241 | } |
12c86877 BH |
242 | d_wrapped=true; |
243 | ||
b8e0f341 | 244 | vector<uint8_t> packet; |
adf13442 | 245 | DNSPacketWriter pw(packet, qdomain, qtype.getCode(), qclass); |
12c86877 | 246 | |
6f966e0b | 247 | pw.getHeader()->rcode=d.rcode; |
b8e0f341 BH |
248 | pw.getHeader()->aa=d.aa; |
249 | pw.getHeader()->ra=d.ra; | |
250 | pw.getHeader()->qr=d.qr; | |
251 | pw.getHeader()->id=d.id; | |
252 | pw.getHeader()->rd=d.rd; | |
12c86877 | 253 | |
7f7b8d55 BH |
254 | DNSPacketWriter::optvect_t opts; |
255 | if(d_wantsnsid) { | |
256 | opts.push_back(make_pair(3, ::arg()["server-id"])); | |
257 | } | |
258 | ||
259 | if(!d_ednsping.empty()) { | |
260 | opts.push_back(make_pair(4, d_ednsping)); | |
261 | } | |
262 | ||
9c92ad4b | 263 | if(!d_rrs.empty() || !opts.empty()) { |
6f966e0b | 264 | try { |
9c92ad4b | 265 | for(pos=d_rrs.begin(); pos < d_rrs.end(); ++pos) { |
379005d3 | 266 | // this needs to deal with the 'prio' mismatch: |
4957a608 BH |
267 | if(pos->qtype.getCode()==QType::MX || pos->qtype.getCode() == QType::SRV) { |
268 | pos->content = lexical_cast<string>(pos->priority) + " " + pos->content; | |
269 | } | |
9c92ad4b | 270 | |
4957a608 BH |
271 | if(!pos->content.empty() && pos->qtype.getCode()==QType::TXT && pos->content[0]!='"') { |
272 | pos->content="\""+pos->content+"\""; | |
273 | } | |
274 | if(pos->content.empty()) // empty contents confuse the MOADNS setup | |
275 | pos->content="."; | |
e02d0a59 | 276 | |
95369951 BH |
277 | pw.startRecord(pos->qname, pos->qtype.getCode(), pos->ttl, pos->qclass, (DNSPacketWriter::Place)pos->d_place); |
278 | shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(pos->qtype.getCode(), 1, pos->content)); | |
279 | drc->toPacket(pw); | |
dffbaa08 | 280 | if(pw.size() + 20U > (d_tcp ? 65535 : getMaxReplyLen())) { // 20 = room for EDNS0 |
95369951 BH |
281 | pw.rollback(); |
282 | if(pos->d_place == DNSResourceRecord::ANSWER) { | |
283 | pw.getHeader()->tc=1; | |
284 | } | |
285 | goto noCommit; | |
95369951 BH |
286 | } |
287 | } | |
9c92ad4b BH |
288 | |
289 | if(!opts.empty() || d_dnssecOk) | |
95369951 | 290 | pw.addOpt(2800, 0, d_dnssecOk ? EDNSOpts::DNSSECOK : 0, opts); |
7f7b8d55 | 291 | |
cb6cc5db | 292 | if(!pw.getHeader()->tc) // protect against double commit from addSignature |
95369951 BH |
293 | pw.commit(); |
294 | noCommit:; | |
6f966e0b | 295 | } |
5172cb78 | 296 | catch(std::exception& e) { |
07676510 | 297 | L<<Logger::Warning<<"Exception: "<<e.what()<<endl; |
6f966e0b | 298 | throw; |
12c86877 | 299 | } |
b8e0f341 | 300 | } |
78bcb858 BH |
301 | |
302 | if(!d_trc.d_algoName.empty()) | |
01cb2fe2 | 303 | addTSIG(pw, &d_trc, d_tsigkeyname, d_tsigsecret, d_tsigprevious, d_tsigtimersonly); |
78bcb858 BH |
304 | |
305 | d_rawpacket.assign((char*)&packet[0], packet.size()); | |
12c86877 BH |
306 | } |
307 | ||
288f4aa9 | 308 | void DNSPacket::setQuestion(int op, const string &qd, int newqtype) |
12c86877 BH |
309 | { |
310 | memset(&d,0,sizeof(d)); | |
311 | d.id=Utility::random(); | |
312 | d.rd=d.tc=d.aa=false; | |
313 | d.qr=false; | |
314 | d.qdcount=1; // is htons'ed later on | |
315 | d.ancount=d.arcount=d.nscount=0; | |
316 | d.opcode=op; | |
288f4aa9 BH |
317 | qdomain=qd; |
318 | qtype=newqtype; | |
12c86877 BH |
319 | } |
320 | ||
12c86877 BH |
321 | /** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */ |
322 | DNSPacket *DNSPacket::replyPacket() const | |
323 | { | |
324 | DNSPacket *r=new DNSPacket; | |
325 | r->setSocket(d_socket); | |
326 | ||
d06799d4 | 327 | r->setRemote(&d_remote); |
12c86877 BH |
328 | r->setAnswer(true); // this implies the allocation of the header |
329 | r->setA(true); // and we are authoritative | |
330 | r->setRA(0); // no recursion available | |
78bcb858 | 331 | r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it |
12c86877 BH |
332 | r->setID(d.id); |
333 | r->setOpcode(d.opcode); | |
334 | ||
12c86877 | 335 | r->d_dt=d_dt; |
092c9cc4 | 336 | r->d.qdcount=1; |
f28307ad | 337 | r->d_tcp = d_tcp; |
b8e0f341 BH |
338 | r->qdomain = qdomain; |
339 | r->qtype = qtype; | |
adf13442 | 340 | r->qclass = qclass; |
657e9124 | 341 | r->d_maxreplylen = d_maxreplylen; |
7f7b8d55 BH |
342 | r->d_ednsping = d_ednsping; |
343 | r->d_wantsnsid = d_wantsnsid; | |
9c92ad4b | 344 | r->d_dnssecOk = d_dnssecOk; |
78bcb858 BH |
345 | |
346 | if(!d_tsigkeyname.empty()) { | |
347 | r->d_tsigkeyname = d_tsigkeyname; | |
348 | r->d_tsigprevious = d_tsigprevious; | |
349 | r->d_trc = d_trc; | |
350 | r->d_tsigsecret = d_tsigsecret; | |
351 | r->d_tsigtimersonly = d_tsigtimersonly; | |
352 | } | |
6dc26cf0 | 353 | r->d_havetsig = d_havetsig; |
12c86877 BH |
354 | return r; |
355 | } | |
356 | ||
b8e0f341 | 357 | void DNSPacket::spoofQuestion(const string &qd) |
12c86877 | 358 | { |
b8e0f341 | 359 | string label=simpleCompress(qd); |
b8e0f341 | 360 | d_wrapped=true; // if we do this, don't later on wrapup |
7de6b0d5 BH |
361 | |
362 | if(label.size() + sizeof(d) > d_rawpacket.size()) { // probably superfluous | |
363 | return; | |
364 | } | |
365 | ||
366 | for(string::size_type i=0; i < label.size(); ++i) | |
367 | d_rawpacket[i+sizeof(d)]=label[i]; | |
368 | ||
b8e0f341 | 369 | } |
12c86877 | 370 | |
07676510 BH |
371 | int DNSPacket::noparse(const char *mesg, int length) |
372 | { | |
78bcb858 | 373 | d_rawpacket.assign(mesg,length); |
07676510 BH |
374 | if(length < 12) { |
375 | L << Logger::Warning << "Ignoring packet: too short from " | |
376 | << getRemote() << endl; | |
377 | return -1; | |
378 | } | |
379 | d_wantsnsid=false; | |
380 | d_ednsping.clear(); | |
381 | d_maxreplylen=512; | |
78bcb858 | 382 | memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12); |
07676510 BH |
383 | return 0; |
384 | } | |
385 | ||
78bcb858 BH |
386 | void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const string& keyname, const string& secret, const string& previous, bool timersonly) |
387 | { | |
388 | d_trc=tr; | |
389 | d_tsigkeyname = keyname; | |
390 | d_tsigsecret = secret; | |
391 | d_tsigprevious = previous; | |
392 | d_tsigtimersonly=timersonly; | |
393 | } | |
394 | ||
78bcb858 BH |
395 | bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, string* keyname, string* message) const |
396 | { | |
397 | MOADNSParser mdp(d_rawpacket); | |
398 | ||
399 | if(!mdp.getTSIGPos()) | |
400 | return false; | |
401 | ||
402 | bool gotit=false; | |
403 | for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { | |
404 | if(i->first.d_type == QType::TSIG) { | |
405 | *trc = *boost::dynamic_pointer_cast<TSIGRecordContent>(i->first.d_content); | |
406 | ||
407 | gotit=true; | |
408 | *keyname = i->first.d_label; | |
6507e8e8 BH |
409 | if(!keyname->empty()) |
410 | keyname->resize(keyname->size()-1); // drop the trailing dot | |
78bcb858 BH |
411 | } |
412 | } | |
413 | if(!gotit) | |
414 | return false; | |
01cb2fe2 BH |
415 | if(message) |
416 | *message = makeTSIGMessageFromTSIGPacket(d_rawpacket, mdp.getTSIGPos(), *keyname, *trc, d_tsigprevious, false); // if you change rawpacket to getString it breaks! | |
78bcb858 | 417 | |
78bcb858 BH |
418 | return true; |
419 | } | |
420 | ||
b8e0f341 BH |
421 | /** This function takes data from the network, possibly received with recvfrom, and parses |
422 | it into our class. Results of calling this function multiple times on one packet are | |
423 | unknown. Returns -1 if the packet cannot be parsed. | |
424 | */ | |
425 | int DNSPacket::parse(const char *mesg, int length) | |
9f064e90 | 426 | try |
b8e0f341 | 427 | { |
78bcb858 | 428 | d_rawpacket.assign(mesg,length); |
0e7f49b5 | 429 | d_wrapped=true; |
b8e0f341 BH |
430 | if(length < 12) { |
431 | L << Logger::Warning << "Ignoring packet: too short from " | |
432 | << getRemote() << endl; | |
433 | return -1; | |
434 | } | |
7f7b8d55 | 435 | |
78bcb858 | 436 | MOADNSParser mdp(d_rawpacket); |
7f7b8d55 BH |
437 | EDNSOpts edo; |
438 | ||
439 | // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST! | |
440 | ||
441 | d_wantsnsid=false; | |
9c92ad4b | 442 | d_dnssecOk=false; |
7f7b8d55 | 443 | d_ednsping.clear(); |
78bcb858 | 444 | d_havetsig = mdp.getTSIGPos(); |
7f7b8d55 | 445 | |
9c92ad4b | 446 | |
7f7b8d55 | 447 | if(getEDNSOpts(mdp, &edo)) { |
10f4eea8 | 448 | d_maxreplylen=std::min(edo.d_packetsize, (uint16_t)1680); |
d28f1bd6 | 449 | // cerr<<edo.d_Z<<endl; |
9c92ad4b BH |
450 | if(edo.d_Z & EDNSOpts::DNSSECOK) |
451 | d_dnssecOk=true; | |
7f7b8d55 BH |
452 | |
453 | for(vector<pair<uint16_t, string> >::const_iterator iter = edo.d_options.begin(); | |
4957a608 BH |
454 | iter != edo.d_options.end(); |
455 | ++iter) { | |
7f7b8d55 | 456 | if(iter->first == 3) {// 'EDNS NSID' |
4957a608 | 457 | d_wantsnsid=1; |
7f7b8d55 | 458 | } |
deff621d | 459 | else if(iter->first == 5) {// 'EDNS PING' |
4957a608 | 460 | d_ednsping = iter->second; |
7f7b8d55 BH |
461 | } |
462 | else | |
4957a608 | 463 | ; // cerr<<"Have an option #"<<iter->first<<endl; |
7f7b8d55 | 464 | } |
657e9124 | 465 | } |
7f7b8d55 | 466 | else { |
657e9124 | 467 | d_maxreplylen=512; |
7f7b8d55 | 468 | } |
12c86877 | 469 | |
78bcb858 | 470 | memcpy((void *)&d,(const void *)d_rawpacket.c_str(),12); |
b8e0f341 BH |
471 | qdomain=mdp.d_qname; |
472 | if(!qdomain.empty()) // strip dot | |
61b26744 | 473 | boost::erase_tail(qdomain, 1); |
12c86877 | 474 | |
b8e0f341 BH |
475 | if(!ntohs(d.qdcount)) { |
476 | if(!d_tcp) { | |
477 | L << Logger::Warning << "No question section in packet from " << getRemote() <<", rcode="<<(int)d.rcode<<endl; | |
478 | return -1; | |
12c86877 BH |
479 | } |
480 | } | |
481 | ||
b8e0f341 BH |
482 | qtype=mdp.d_qtype; |
483 | qclass=mdp.d_qclass; | |
484 | return 0; | |
12c86877 | 485 | } |
5172cb78 | 486 | catch(std::exception& e) { |
9f064e90 BH |
487 | return -1; |
488 | } | |
12c86877 | 489 | |
78bcb858 | 490 | unsigned int DNSPacket::getMaxReplyLen() |
657e9124 BH |
491 | { |
492 | return d_maxreplylen; | |
493 | } | |
494 | ||
80397312 BH |
495 | void DNSPacket::setMaxReplyLen(int bytes) |
496 | { | |
497 | d_maxreplylen=bytes; | |
498 | } | |
499 | ||
b8e0f341 BH |
500 | //! Use this to set where this packet was received from or should be sent to |
501 | void DNSPacket::setRemote(const ComboAddress *s) | |
12c86877 | 502 | { |
d06799d4 | 503 | d_remote=*s; |
b8e0f341 | 504 | } |
12c86877 | 505 | |
b8e0f341 | 506 | void DNSPacket::setSocket(Utility::sock_t sock) |
12c86877 | 507 | { |
b8e0f341 | 508 | d_socket=sock; |
12c86877 BH |
509 | } |
510 | ||
b8e0f341 | 511 | void DNSPacket::commitD() |
12c86877 | 512 | { |
78bcb858 | 513 | d_rawpacket.replace(0,12,(char *)&d,12); // copy in d |
12c86877 BH |
514 | } |
515 | ||
78bcb858 BH |
516 | bool checkForCorrectTSIG(const DNSPacket* q, DNSBackend* B, string* keyname, string* secret, TSIGRecordContent* trc) |
517 | { | |
518 | string message; | |
519 | ||
520 | q->getTSIGDetails(trc, keyname, &message); | |
521 | uint64_t now = time(0); | |
522 | if(abs(trc->d_time - now) > trc->d_fudge) { | |
6dc26cf0 | 523 | L<<Logger::Error<<"Packet for '"<<q->qdomain<<"' denied: TSIG (key '"<<*keyname<<"') time delta "<< abs(trc->d_time - now)<<" > 'fudge' "<<trc->d_fudge<<endl; |
78bcb858 BH |
524 | return false; |
525 | } | |
526 | ||
527 | string secret64; | |
528 | ||
529 | if(!B->getTSIGKey(*keyname, &trc->d_algoName, &secret64)) { | |
530 | L<<Logger::Error<<"Packet for domain '"<<q->qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<<trc->d_algoName<<"'"<<endl; | |
531 | return false; | |
532 | } | |
20665beb | 533 | trc->d_algoName += ".sig-alg.reg.int."; |
78bcb858 BH |
534 | B64Decode(secret64, *secret); |
535 | bool result=calculateMD5HMAC(*secret, message) == trc->d_mac; | |
536 | if(!result) { | |
537 | L<<Logger::Error<<"Packet for domain '"<<q->qdomain<<"' denied: TSIG signature mismatch using '"<<*keyname<<"' and algorithm '"<<trc->d_algoName<<"'"<<endl; | |
538 | } | |
539 | return result; | |
540 | } |