]>
Commit | Line | Data |
---|---|---|
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 | 27 | class NSECBitmapGenerator |
e64fccad | 28 | { |
27d4a65b RG |
29 | public: |
30 | NSECBitmapGenerator(DNSPacketWriter& pw_): pw(pw_) | |
31 | { | |
e64fccad | 32 | } |
27d4a65b RG |
33 | void set(uint16_t type) |
34 | { | |
35 | uint16_t bit = type % 256; | |
36 | int window = static_cast<int>(type / 256); | |
e64fccad | 37 | |
5b7f6546 PD |
38 | if (window != oldWindow) { |
39 | if (oldWindow > -1) { | |
27d4a65b RG |
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); | |
5b7f6546 PD |
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 | ||
27d4a65b RG |
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; | |
9f607f21 | 79 | for(size_t idx = 0; idx < nbTypes && found < count; ++idx){ |
27d4a65b RG |
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(); | |
e64fccad BH |
94 | } |
95 | ||
27d4a65b | 96 | void NSECBitmap::fromPacket(PacketReader& pr) |
e64fccad | 97 | { |
e64fccad BH |
98 | string bitmap; |
99 | pr.xfrBlob(bitmap); | |
27d4a65b | 100 | |
e64fccad | 101 | // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left |
27d4a65b RG |
102 | if(bitmap.empty()) { |
103 | return; | |
104 | } | |
5b7f6546 | 105 | |
27d4a65b | 106 | if(bitmap.size() < 2) { |
e64fccad | 107 | throw MOADNSException("NSEC record with impossibly small bitmap"); |
27d4a65b | 108 | } |
e64fccad | 109 | |
5b7f6546 PD |
110 | for(unsigned int n = 0; n+1 < bitmap.size();) { |
111 | unsigned int window=static_cast<unsigned char>(bitmap[n++]); | |
dd079764 | 112 | unsigned int blen=static_cast<unsigned char>(bitmap[n++]); |
5b7f6546 PD |
113 | |
114 | // end if zero padding and ensure packet length | |
27d4a65b RG |
115 | if(window == 0 && blen == 0) { |
116 | break; | |
117 | } | |
118 | ||
119 | if(n + blen > bitmap.size()) { | |
5b7f6546 | 120 | throw MOADNSException("NSEC record with bitmap length > packet length"); |
27d4a65b | 121 | } |
5b7f6546 | 122 | |
dd079764 | 123 | for(unsigned int k=0; k < blen; k++) { |
5b7f6546 | 124 | uint8_t val=bitmap[n++]; |
27d4a65b | 125 | for(int bit = 0; bit < 8 ; ++bit , val>>=1) { |
dd079764 | 126 | if(val & 1) { |
27d4a65b | 127 | set((7-bit) + 8*(k) + 256*window); |
5b7f6546 | 128 | } |
e64fccad | 129 | } |
27d4a65b RG |
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; | |
9f607f21 | 141 | for(size_t idx = 0; idx < nbTypes && found < count; ++idx) { |
27d4a65b RG |
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); | |
e64fccad | 180 | } |
27d4a65b RG |
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 | ||
e64fccad BH |
196 | return ret; |
197 | } | |
198 | ||
f21fc0aa | 199 | string NSECRecordContent::getZoneRepresentation(bool noDot) const |
e64fccad BH |
200 | { |
201 | string ret; | |
202 | RecordTextWriter rtw(ret); | |
ad8fa726 | 203 | rtw.xfrName(d_next); |
27d4a65b RG |
204 | |
205 | return ret + d_bitmap.getZoneRepresentation(); | |
e64fccad BH |
206 | } |
207 | ||
208 | ////// begin of NSEC3 | |
209 | ||
210 | void NSEC3RecordContent::report(void) | |
211 | { | |
212 | regist(1, 50, &make, &make, "NSEC3"); | |
213 | } | |
214 | ||
32122aab | 215 | std::shared_ptr<DNSRecordContent> NSEC3RecordContent::make(const string& content) |
e64fccad | 216 | { |
32122aab | 217 | return std::make_shared<NSEC3RecordContent>(content); |
e64fccad BH |
218 | } |
219 | ||
5a1f298f | 220 | NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone) |
e64fccad | 221 | { |
3716f081 | 222 | RecordTextReader rtr(content, DNSName(zone)); |
e64fccad BH |
223 | rtr.xfr8BitInt(d_algorithm); |
224 | rtr.xfr8BitInt(d_flags); | |
225 | rtr.xfr16BitInt(d_iterations); | |
226 | ||
227 | rtr.xfrHexBlob(d_salt); | |
8b606f6e BH |
228 | rtr.xfrBase32HexBlob(d_nexthash); |
229 | ||
e64fccad BH |
230 | while(!rtr.eof()) { |
231 | uint16_t type; | |
232 | rtr.xfrType(type); | |
27d4a65b | 233 | set(type); |
e64fccad BH |
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); | |
e64fccad | 247 | |
27d4a65b | 248 | d_bitmap.toPacket(pw); |
e64fccad BH |
249 | } |
250 | ||
32122aab | 251 | std::shared_ptr<NSEC3RecordContent::DNSRecordContent> NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr) |
e64fccad | 252 | { |
32122aab | 253 | auto ret=std::make_shared<NSEC3RecordContent>(); |
e64fccad BH |
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); | |
5b7f6546 | 263 | |
27d4a65b | 264 | ret->d_bitmap.fromPacket(pr); |
e64fccad BH |
265 | return ret; |
266 | } | |
267 | ||
f21fc0aa | 268 | string NSEC3RecordContent::getZoneRepresentation(bool noDot) const |
e64fccad BH |
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); | |
1c4d88c5 | 277 | rtw.xfrBase32HexBlob(d_nexthash); |
27d4a65b RG |
278 | |
279 | return ret + d_bitmap.getZoneRepresentation(); | |
e64fccad BH |
280 | } |
281 | ||
282 | ||
827634f0 BH |
283 | void NSEC3PARAMRecordContent::report(void) |
284 | { | |
285 | regist(1, 51, &make, &make, "NSEC3PARAM"); | |
dff32e09 | 286 | regist(254, 51, &make, &make, "NSEC3PARAM"); |
827634f0 BH |
287 | } |
288 | ||
32122aab | 289 | std::shared_ptr<DNSRecordContent> NSEC3PARAMRecordContent::make(const string& content) |
827634f0 | 290 | { |
32122aab | 291 | return std::make_shared<NSEC3PARAMRecordContent>(content); |
827634f0 BH |
292 | } |
293 | ||
5a1f298f | 294 | NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const string& zone) |
827634f0 | 295 | { |
3716f081 | 296 | RecordTextReader rtr(content, DNSName(zone)); |
827634f0 | 297 | rtr.xfr8BitInt(d_algorithm); |
8b606f6e BH |
298 | rtr.xfr8BitInt(d_flags); |
299 | rtr.xfr16BitInt(d_iterations); | |
827634f0 BH |
300 | rtr.xfrHexBlob(d_salt); |
301 | } | |
302 | ||
303 | void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw) | |
304 | { | |
305 | pw.xfr8BitInt(d_algorithm); | |
232f0877 CH |
306 | pw.xfr8BitInt(d_flags); |
307 | pw.xfr16BitInt(d_iterations); | |
827634f0 | 308 | pw.xfr8BitInt(d_salt.length()); |
c68cc098 | 309 | // cerr<<"salt: '"<<makeHexDump(d_salt)<<"', "<<d_salt.length()<<endl; |
827634f0 BH |
310 | pw.xfrBlob(d_salt); |
311 | } | |
312 | ||
32122aab | 313 | std::shared_ptr<NSEC3PARAMRecordContent::DNSRecordContent> NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr) |
827634f0 | 314 | { |
32122aab | 315 | auto ret=std::make_shared<NSEC3PARAMRecordContent>(); |
827634f0 | 316 | pr.xfr8BitInt(ret->d_algorithm); |
232f0877 CH |
317 | pr.xfr8BitInt(ret->d_flags); |
318 | pr.xfr16BitInt(ret->d_iterations); | |
a82f68f0 RG |
319 | uint8_t len; |
320 | pr.xfr8BitInt(len); | |
321 | pr.xfrHexBlob(ret->d_salt, len); | |
827634f0 BH |
322 | return ret; |
323 | } | |
324 | ||
f21fc0aa | 325 | string NSEC3PARAMRecordContent::getZoneRepresentation(bool noDot) const |
827634f0 BH |
326 | { |
327 | string ret; | |
328 | RecordTextWriter rtw(ret); | |
329 | rtw.xfr8BitInt(d_algorithm); | |
232f0877 CH |
330 | rtw.xfr8BitInt(d_flags); |
331 | rtw.xfr16BitInt(d_iterations); | |
827634f0 BH |
332 | rtw.xfrHexBlob(d_salt); |
333 | return ret; | |
334 | } | |
335 |