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