]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/nsecrecords.cc
Merge pull request #7351 from jsoref/tests-output
[thirdparty/pdns.git] / pdns / nsecrecords.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 "dnsrecords.hh"
26
27 class NSECBitmapGenerator
28 {
29 public:
30 NSECBitmapGenerator(DNSPacketWriter& pw_): pw(pw_)
31 {
32 }
33 void set(uint16_t type)
34 {
35 uint16_t bit = type % 256;
36 int window = static_cast<int>(type / 256);
37
38 if (window != oldWindow) {
39 if (oldWindow > -1) {
40 res[0] = static_cast<unsigned char>(oldWindow);
41 res[1] = static_cast<unsigned char>(len);
42 tmp.assign(res, res+len+2);
43 pw.xfrBlob(tmp);
44 }
45 memset(res, 0, 34);
46 oldWindow = window;
47 }
48 res[2+bit/8] |= 1 << (7-(bit%8));
49 len=1+bit/8;
50 }
51
52 void finish()
53 {
54 res[0] = static_cast<unsigned char>(oldWindow);
55 res[1] = static_cast<unsigned char>(len);
56 if (len) {
57 tmp.assign(res, res+len+2);
58 pw.xfrBlob(tmp);
59 }
60 }
61
62 private:
63 DNSPacketWriter& pw;
64 /* one byte for the window,
65 one for the length,
66 then the maximum of 32 bytes */
67 uint8_t res[34];
68 int oldWindow{-1};
69 int len{0};
70 string tmp;
71 };
72
73 void NSECBitmap::toPacket(DNSPacketWriter& pw)
74 {
75 NSECBitmapGenerator nbg(pw);
76 if (d_bitset) {
77 size_t count = d_bitset->count();
78 size_t found = 0;
79 for(size_t idx = 0; idx < nbTypes && found < count; ++idx){
80 if (!d_bitset->test(idx)) {
81 continue;
82 }
83 found++;
84 nbg.set(idx);
85 }
86 }
87 else {
88 for (const auto& type : d_set) {
89 nbg.set(type);
90 }
91 }
92
93 nbg.finish();
94 }
95
96 void NSECBitmap::fromPacket(PacketReader& pr)
97 {
98 string bitmap;
99 pr.xfrBlob(bitmap);
100
101 // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left
102 if(bitmap.empty()) {
103 return;
104 }
105
106 if(bitmap.size() < 2) {
107 throw MOADNSException("NSEC record with impossibly small bitmap");
108 }
109
110 for(unsigned int n = 0; n+1 < bitmap.size();) {
111 unsigned int window=static_cast<unsigned char>(bitmap[n++]);
112 unsigned int blen=static_cast<unsigned char>(bitmap[n++]);
113
114 // end if zero padding and ensure packet length
115 if(window == 0 && blen == 0) {
116 break;
117 }
118
119 if(n + blen > bitmap.size()) {
120 throw MOADNSException("NSEC record with bitmap length > packet length");
121 }
122
123 for(unsigned int k=0; k < blen; k++) {
124 uint8_t val=bitmap[n++];
125 for(int bit = 0; bit < 8 ; ++bit , val>>=1) {
126 if(val & 1) {
127 set((7-bit) + 8*(k) + 256*window);
128 }
129 }
130 }
131 }
132 }
133
134 string NSECBitmap::getZoneRepresentation() const
135 {
136 string ret;
137
138 if (d_bitset) {
139 size_t count = d_bitset->count();
140 size_t found = 0;
141 for(size_t idx = 0; idx < nbTypes && found < count; ++idx) {
142 if (!d_bitset->test(idx)) {
143 continue;
144 }
145 found++;
146
147 ret+=" ";
148 ret+=DNSRecordContent::NumberToType(idx);
149 }
150 }
151 else {
152 for(const auto& type : d_set) {
153 ret+=" ";
154 ret+=DNSRecordContent::NumberToType(type);
155 }
156 }
157
158 return ret;
159 }
160
161 void NSECRecordContent::report(void)
162 {
163 regist(1, 47, &make, &make, "NSEC");
164 }
165
166 std::shared_ptr<DNSRecordContent> NSECRecordContent::make(const string& content)
167 {
168 return std::make_shared<NSECRecordContent>(content);
169 }
170
171 NSECRecordContent::NSECRecordContent(const string& content, const string& zone)
172 {
173 RecordTextReader rtr(content, DNSName(zone));
174 rtr.xfrName(d_next);
175
176 while(!rtr.eof()) {
177 uint16_t type;
178 rtr.xfrType(type);
179 set(type);
180 }
181 }
182
183 void NSECRecordContent::toPacket(DNSPacketWriter& pw)
184 {
185 pw.xfrName(d_next);
186 d_bitmap.toPacket(pw);
187 }
188
189 std::shared_ptr<NSECRecordContent::DNSRecordContent> NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr)
190 {
191 auto ret=std::make_shared<NSECRecordContent>();
192 pr.xfrName(ret->d_next);
193
194 ret->d_bitmap.fromPacket(pr);
195
196 return ret;
197 }
198
199 string NSECRecordContent::getZoneRepresentation(bool noDot) const
200 {
201 string ret;
202 RecordTextWriter rtw(ret);
203 rtw.xfrName(d_next);
204
205 return ret + d_bitmap.getZoneRepresentation();
206 }
207
208 ////// begin of NSEC3
209
210 void NSEC3RecordContent::report(void)
211 {
212 regist(1, 50, &make, &make, "NSEC3");
213 }
214
215 std::shared_ptr<DNSRecordContent> NSEC3RecordContent::make(const string& content)
216 {
217 return std::make_shared<NSEC3RecordContent>(content);
218 }
219
220 NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone)
221 {
222 RecordTextReader rtr(content, DNSName(zone));
223 rtr.xfr8BitInt(d_algorithm);
224 rtr.xfr8BitInt(d_flags);
225 rtr.xfr16BitInt(d_iterations);
226
227 rtr.xfrHexBlob(d_salt);
228 rtr.xfrBase32HexBlob(d_nexthash);
229
230 while(!rtr.eof()) {
231 uint16_t type;
232 rtr.xfrType(type);
233 set(type);
234 }
235 }
236
237 void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
238 {
239 pw.xfr8BitInt(d_algorithm);
240 pw.xfr8BitInt(d_flags);
241 pw.xfr16BitInt(d_iterations);
242 pw.xfr8BitInt(d_salt.length());
243 pw.xfrBlob(d_salt);
244
245 pw.xfr8BitInt(d_nexthash.length());
246 pw.xfrBlob(d_nexthash);
247
248 d_bitmap.toPacket(pw);
249 }
250
251 std::shared_ptr<NSEC3RecordContent::DNSRecordContent> NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr)
252 {
253 auto ret=std::make_shared<NSEC3RecordContent>();
254 pr.xfr8BitInt(ret->d_algorithm);
255 pr.xfr8BitInt(ret->d_flags);
256 pr.xfr16BitInt(ret->d_iterations);
257 uint8_t len;
258 pr.xfr8BitInt(len);
259 pr.xfrBlob(ret->d_salt, len);
260
261 pr.xfr8BitInt(len);
262 pr.xfrBlob(ret->d_nexthash, len);
263
264 ret->d_bitmap.fromPacket(pr);
265 return ret;
266 }
267
268 string NSEC3RecordContent::getZoneRepresentation(bool noDot) const
269 {
270 string ret;
271 RecordTextWriter rtw(ret);
272 rtw.xfr8BitInt(d_algorithm);
273 rtw.xfr8BitInt(d_flags);
274 rtw.xfr16BitInt(d_iterations);
275
276 rtw.xfrHexBlob(d_salt);
277 rtw.xfrBase32HexBlob(d_nexthash);
278
279 return ret + d_bitmap.getZoneRepresentation();
280 }
281
282
283 void NSEC3PARAMRecordContent::report(void)
284 {
285 regist(1, 51, &make, &make, "NSEC3PARAM");
286 regist(254, 51, &make, &make, "NSEC3PARAM");
287 }
288
289 std::shared_ptr<DNSRecordContent> NSEC3PARAMRecordContent::make(const string& content)
290 {
291 return std::make_shared<NSEC3PARAMRecordContent>(content);
292 }
293
294 NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const string& zone)
295 {
296 RecordTextReader rtr(content, DNSName(zone));
297 rtr.xfr8BitInt(d_algorithm);
298 rtr.xfr8BitInt(d_flags);
299 rtr.xfr16BitInt(d_iterations);
300 rtr.xfrHexBlob(d_salt);
301 }
302
303 void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw)
304 {
305 pw.xfr8BitInt(d_algorithm);
306 pw.xfr8BitInt(d_flags);
307 pw.xfr16BitInt(d_iterations);
308 pw.xfr8BitInt(d_salt.length());
309 // cerr<<"salt: '"<<makeHexDump(d_salt)<<"', "<<d_salt.length()<<endl;
310 pw.xfrBlob(d_salt);
311 }
312
313 std::shared_ptr<NSEC3PARAMRecordContent::DNSRecordContent> NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr)
314 {
315 auto ret=std::make_shared<NSEC3PARAMRecordContent>();
316 pr.xfr8BitInt(ret->d_algorithm);
317 pr.xfr8BitInt(ret->d_flags);
318 pr.xfr16BitInt(ret->d_iterations);
319 uint8_t len;
320 pr.xfr8BitInt(len);
321 pr.xfrHexBlob(ret->d_salt, len);
322 return ret;
323 }
324
325 string NSEC3PARAMRecordContent::getZoneRepresentation(bool noDot) const
326 {
327 string ret;
328 RecordTextWriter rtw(ret);
329 rtw.xfr8BitInt(d_algorithm);
330 rtw.xfr8BitInt(d_flags);
331 rtw.xfr16BitInt(d_iterations);
332 rtw.xfrHexBlob(d_salt);
333 return ret;
334 }
335