]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/nsecrecords.cc
Meson: Separate test files from common files
[thirdparty/pdns.git] / pdns / nsecrecords.cc
CommitLineData
12471842
PL
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 */
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
e64fccad
BH
25#include "dnsrecords.hh"
26
27d4a65b 27class NSECBitmapGenerator
e64fccad 28{
27d4a65b
RG
29public:
30 NSECBitmapGenerator(DNSPacketWriter& pw_): pw(pw_)
31 {
acefbd3c 32 memset(res, 0, sizeof(res));
e64fccad 33 }
d031fa7c 34
27d4a65b
RG
35 void set(uint16_t type)
36 {
37 uint16_t bit = type % 256;
38 int window = static_cast<int>(type / 256);
e64fccad 39
5b7f6546
PD
40 if (window != oldWindow) {
41 if (oldWindow > -1) {
27d4a65b
RG
42 res[0] = static_cast<unsigned char>(oldWindow);
43 res[1] = static_cast<unsigned char>(len);
44 tmp.assign(res, res+len+2);
45 pw.xfrBlob(tmp);
5b7f6546 46 }
acefbd3c 47 memset(res, 0, sizeof(res));
5b7f6546
PD
48 oldWindow = window;
49 }
50 res[2+bit/8] |= 1 << (7-(bit%8));
51 len=1+bit/8;
52 }
53
27d4a65b
RG
54 void finish()
55 {
56 res[0] = static_cast<unsigned char>(oldWindow);
57 res[1] = static_cast<unsigned char>(len);
58 if (len) {
59 tmp.assign(res, res+len+2);
60 pw.xfrBlob(tmp);
61 }
62 }
63
64private:
65 DNSPacketWriter& pw;
66 /* one byte for the window,
67 one for the length,
68 then the maximum of 32 bytes */
69 uint8_t res[34];
70 int oldWindow{-1};
71 int len{0};
72 string tmp;
73};
74
d06dcda4 75void NSECBitmap::toPacket(DNSPacketWriter& pw) const
27d4a65b
RG
76{
77 NSECBitmapGenerator nbg(pw);
78 if (d_bitset) {
27d4a65b 79 size_t found = 0;
fd0a95f5
AT
80 size_t l_count = d_bitset->count();
81 for(size_t idx = 0; idx < nbTypes && found < l_count; ++idx){
27d4a65b
RG
82 if (!d_bitset->test(idx)) {
83 continue;
84 }
85 found++;
86 nbg.set(idx);
87 }
88 }
89 else {
90 for (const auto& type : d_set) {
91 nbg.set(type);
92 }
93 }
94
95 nbg.finish();
e64fccad
BH
96}
97
27d4a65b 98void NSECBitmap::fromPacket(PacketReader& pr)
e64fccad 99{
e64fccad
BH
100 string bitmap;
101 pr.xfrBlob(bitmap);
27d4a65b 102
e64fccad 103 // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left
27d4a65b
RG
104 if(bitmap.empty()) {
105 return;
106 }
5b7f6546 107
27d4a65b 108 if(bitmap.size() < 2) {
e64fccad 109 throw MOADNSException("NSEC record with impossibly small bitmap");
27d4a65b 110 }
bb85386d 111
5b7f6546 112 for(unsigned int n = 0; n+1 < bitmap.size();) {
3d51568b
RG
113 uint8_t window=static_cast<uint8_t>(bitmap[n++]);
114 uint8_t blen=static_cast<uint8_t>(bitmap[n++]);
5b7f6546
PD
115
116 // end if zero padding and ensure packet length
3d51568b 117 if (window == 0 && blen == 0) {
27d4a65b
RG
118 break;
119 }
120
3d51568b
RG
121 if (blen > 32) {
122 throw MOADNSException("NSEC record with invalid bitmap length");
123 }
124
125 if (n + blen > bitmap.size()) {
5b7f6546 126 throw MOADNSException("NSEC record with bitmap length > packet length");
27d4a65b 127 }
5b7f6546 128
dd079764 129 for(unsigned int k=0; k < blen; k++) {
5b7f6546 130 uint8_t val=bitmap[n++];
27d4a65b 131 for(int bit = 0; bit < 8 ; ++bit , val>>=1) {
dd079764 132 if(val & 1) {
27d4a65b 133 set((7-bit) + 8*(k) + 256*window);
5b7f6546 134 }
e64fccad 135 }
27d4a65b
RG
136 }
137 }
138}
139
140string NSECBitmap::getZoneRepresentation() const
141{
142 string ret;
143
144 if (d_bitset) {
27d4a65b 145 size_t found = 0;
fd0a95f5
AT
146 size_t l_count = d_bitset->count();
147 for(size_t idx = 0; idx < nbTypes && found < l_count; ++idx) {
27d4a65b
RG
148 if (!d_bitset->test(idx)) {
149 continue;
150 }
151 found++;
152
153 ret+=" ";
154 ret+=DNSRecordContent::NumberToType(idx);
155 }
156 }
157 else {
158 for(const auto& type : d_set) {
159 ret+=" ";
160 ret+=DNSRecordContent::NumberToType(type);
161 }
162 }
163
164 return ret;
165}
166
e52fb6a4 167void NSECRecordContent::report()
27d4a65b
RG
168{
169 regist(1, 47, &make, &make, "NSEC");
170}
171
172std::shared_ptr<DNSRecordContent> NSECRecordContent::make(const string& content)
173{
174 return std::make_shared<NSECRecordContent>(content);
175}
176
a2a77b28 177NSECRecordContent::NSECRecordContent(const string& content, const DNSName& zone)
27d4a65b 178{
a2a77b28 179 RecordTextReader rtr(content, zone);
27d4a65b
RG
180 rtr.xfrName(d_next);
181
182 while(!rtr.eof()) {
183 uint16_t type;
184 rtr.xfrType(type);
185 set(type);
e64fccad 186 }
27d4a65b
RG
187}
188
d06dcda4 189void NSECRecordContent::toPacket(DNSPacketWriter& pw) const
27d4a65b
RG
190{
191 pw.xfrName(d_next);
192 d_bitmap.toPacket(pw);
193}
194
d73de874 195std::shared_ptr<NSECRecordContent::DNSRecordContent> NSECRecordContent::make(const DNSRecord & /* dr */, PacketReader& pr)
27d4a65b
RG
196{
197 auto ret=std::make_shared<NSECRecordContent>();
198 pr.xfrName(ret->d_next);
199
200 ret->d_bitmap.fromPacket(pr);
201
e64fccad
BH
202 return ret;
203}
204
d73de874 205string NSECRecordContent::getZoneRepresentation(bool /* noDot */) const
e64fccad
BH
206{
207 string ret;
208 RecordTextWriter rtw(ret);
ad8fa726 209 rtw.xfrName(d_next);
27d4a65b
RG
210
211 return ret + d_bitmap.getZoneRepresentation();
e64fccad
BH
212}
213
214////// begin of NSEC3
215
e52fb6a4 216void NSEC3RecordContent::report()
e64fccad
BH
217{
218 regist(1, 50, &make, &make, "NSEC3");
219}
220
32122aab 221std::shared_ptr<DNSRecordContent> NSEC3RecordContent::make(const string& content)
e64fccad 222{
32122aab 223 return std::make_shared<NSEC3RecordContent>(content);
e64fccad
BH
224}
225
a2a77b28 226NSEC3RecordContent::NSEC3RecordContent(const string& content, const DNSName& zone)
e64fccad 227{
a2a77b28 228 RecordTextReader rtr(content, zone);
e64fccad
BH
229 rtr.xfr8BitInt(d_algorithm);
230 rtr.xfr8BitInt(d_flags);
231 rtr.xfr16BitInt(d_iterations);
232
233 rtr.xfrHexBlob(d_salt);
8b606f6e 234 rtr.xfrBase32HexBlob(d_nexthash);
bb85386d 235
e64fccad
BH
236 while(!rtr.eof()) {
237 uint16_t type;
238 rtr.xfrType(type);
27d4a65b 239 set(type);
e64fccad
BH
240 }
241}
242
d06dcda4 243void NSEC3RecordContent::toPacket(DNSPacketWriter& pw) const
e64fccad
BH
244{
245 pw.xfr8BitInt(d_algorithm);
246 pw.xfr8BitInt(d_flags);
247 pw.xfr16BitInt(d_iterations);
248 pw.xfr8BitInt(d_salt.length());
249 pw.xfrBlob(d_salt);
250
251 pw.xfr8BitInt(d_nexthash.length());
252 pw.xfrBlob(d_nexthash);
e64fccad 253
27d4a65b 254 d_bitmap.toPacket(pw);
e64fccad
BH
255}
256
d73de874 257std::shared_ptr<NSEC3RecordContent::DNSRecordContent> NSEC3RecordContent::make(const DNSRecord& /* dr */, PacketReader& pr)
e64fccad 258{
32122aab 259 auto ret=std::make_shared<NSEC3RecordContent>();
e64fccad
BH
260 pr.xfr8BitInt(ret->d_algorithm);
261 pr.xfr8BitInt(ret->d_flags);
262 pr.xfr16BitInt(ret->d_iterations);
263 uint8_t len;
264 pr.xfr8BitInt(len);
265 pr.xfrBlob(ret->d_salt, len);
266
267 pr.xfr8BitInt(len);
268 pr.xfrBlob(ret->d_nexthash, len);
5b7f6546 269
27d4a65b 270 ret->d_bitmap.fromPacket(pr);
e64fccad
BH
271 return ret;
272}
273
d73de874 274string NSEC3RecordContent::getZoneRepresentation(bool /* noDot */) const
e64fccad
BH
275{
276 string ret;
277 RecordTextWriter rtw(ret);
278 rtw.xfr8BitInt(d_algorithm);
279 rtw.xfr8BitInt(d_flags);
280 rtw.xfr16BitInt(d_iterations);
281
282 rtw.xfrHexBlob(d_salt);
1c4d88c5 283 rtw.xfrBase32HexBlob(d_nexthash);
27d4a65b
RG
284
285 return ret + d_bitmap.getZoneRepresentation();
e64fccad
BH
286}
287
288
e52fb6a4 289void NSEC3PARAMRecordContent::report()
827634f0
BH
290{
291 regist(1, 51, &make, &make, "NSEC3PARAM");
dff32e09 292 regist(254, 51, &make, &make, "NSEC3PARAM");
827634f0
BH
293}
294
32122aab 295std::shared_ptr<DNSRecordContent> NSEC3PARAMRecordContent::make(const string& content)
827634f0 296{
32122aab 297 return std::make_shared<NSEC3PARAMRecordContent>(content);
827634f0
BH
298}
299
a2a77b28 300NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const DNSName& zone)
827634f0 301{
a2a77b28 302 RecordTextReader rtr(content, zone);
bb85386d
FM
303 rtr.xfr8BitInt(d_algorithm);
304 rtr.xfr8BitInt(d_flags);
305 rtr.xfr16BitInt(d_iterations);
827634f0
BH
306 rtr.xfrHexBlob(d_salt);
307}
308
d06dcda4 309void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw) const
827634f0 310{
bb85386d
FM
311 pw.xfr8BitInt(d_algorithm);
312 pw.xfr8BitInt(d_flags);
313 pw.xfr16BitInt(d_iterations);
827634f0 314 pw.xfr8BitInt(d_salt.length());
c68cc098 315 // cerr<<"salt: '"<<makeHexDump(d_salt)<<"', "<<d_salt.length()<<endl;
827634f0
BH
316 pw.xfrBlob(d_salt);
317}
318
d73de874 319std::shared_ptr<NSEC3PARAMRecordContent::DNSRecordContent> NSEC3PARAMRecordContent::make(const DNSRecord& /* dr */, PacketReader& pr)
827634f0 320{
32122aab 321 auto ret=std::make_shared<NSEC3PARAMRecordContent>();
bb85386d
FM
322 pr.xfr8BitInt(ret->d_algorithm);
323 pr.xfr8BitInt(ret->d_flags);
324 pr.xfr16BitInt(ret->d_iterations);
a82f68f0
RG
325 uint8_t len;
326 pr.xfr8BitInt(len);
327 pr.xfrHexBlob(ret->d_salt, len);
827634f0
BH
328 return ret;
329}
330
d73de874 331string NSEC3PARAMRecordContent::getZoneRepresentation(bool /* noDot */) const
827634f0
BH
332{
333 string ret;
334 RecordTextWriter rtw(ret);
bb85386d
FM
335 rtw.xfr8BitInt(d_algorithm);
336 rtw.xfr8BitInt(d_flags);
337 rtw.xfr16BitInt(d_iterations);
827634f0
BH
338 rtw.xfrHexBlob(d_salt);
339 return ret;
340}
341
3a63bb5f
PD
342////// end of NSEC3
343
344////// begin of CSYNC
345
346void CSYNCRecordContent::report()
347{
348 regist(1, 62, &make, &make, "CSYNC");
349}
350
351std::shared_ptr<DNSRecordContent> CSYNCRecordContent::make(const string& content)
352{
353 return std::make_shared<CSYNCRecordContent>(content);
354}
355
356CSYNCRecordContent::CSYNCRecordContent(const string& content, const DNSName& zone)
357{
358 RecordTextReader rtr(content, zone);
359 rtr.xfr32BitInt(d_serial);
360 rtr.xfr16BitInt(d_flags);
361
362 while(!rtr.eof()) {
363 uint16_t type;
364 rtr.xfrType(type);
365 set(type);
366 }
367}
368
d06dcda4 369void CSYNCRecordContent::toPacket(DNSPacketWriter& pw) const
3a63bb5f
PD
370{
371 pw.xfr32BitInt(d_serial);
372 pw.xfr16BitInt(d_flags);
373
374 d_bitmap.toPacket(pw);
375}
376
d73de874 377std::shared_ptr<CSYNCRecordContent::DNSRecordContent> CSYNCRecordContent::make(const DNSRecord& /* dr */, PacketReader& pr)
3a63bb5f
PD
378{
379 auto ret=std::make_shared<CSYNCRecordContent>();
380 pr.xfr32BitInt(ret->d_serial);
381 pr.xfr16BitInt(ret->d_flags);
382
383 ret->d_bitmap.fromPacket(pr);
384 return ret;
385}
386
d73de874 387string CSYNCRecordContent::getZoneRepresentation(bool /* noDot */) const
3a63bb5f
PD
388{
389 string ret;
390 RecordTextWriter rtw(ret);
391 rtw.xfr32BitInt(d_serial);
392 rtw.xfr16BitInt(d_flags);
393
394 return ret + d_bitmap.getZoneRepresentation();
395}
396
397////// end of CSYNC