/src/bind9/lib/dns/rdata/generic/hip_55.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | /* RFC 5205 */ |
15 | | |
16 | | #pragma once |
17 | | |
18 | 36.7k | #define RRTYPE_HIP_ATTRIBUTES (0) |
19 | | |
20 | | static isc_result_t |
21 | 3.58k | fromtext_hip(ARGS_FROMTEXT) { |
22 | 3.58k | isc_token_t token; |
23 | 3.58k | isc_buffer_t buffer; |
24 | 3.58k | isc_buffer_t hit_len; |
25 | 3.58k | isc_buffer_t key_len; |
26 | 3.58k | unsigned char *start; |
27 | 3.58k | size_t len; |
28 | | |
29 | 3.58k | REQUIRE(type == dns_rdatatype_hip); |
30 | | |
31 | 3.58k | UNUSED(type); |
32 | 3.58k | UNUSED(rdclass); |
33 | 3.58k | UNUSED(callbacks); |
34 | | |
35 | | /* |
36 | | * Dummy HIT len. |
37 | | */ |
38 | 3.58k | hit_len = *target; |
39 | 3.58k | RETERR(uint8_tobuffer(0, target)); |
40 | | |
41 | | /* |
42 | | * Algorithm. |
43 | | */ |
44 | 3.58k | RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, |
45 | 3.58k | false)); |
46 | 3.57k | if (token.value.as_ulong > 0xffU) { |
47 | 38 | RETTOK(ISC_R_RANGE); |
48 | 38 | } |
49 | 3.53k | RETERR(uint8_tobuffer(token.value.as_ulong, target)); |
50 | | |
51 | | /* |
52 | | * Dummy KEY len. |
53 | | */ |
54 | 3.53k | key_len = *target; |
55 | 3.53k | RETERR(uint16_tobuffer(0, target)); |
56 | | |
57 | | /* |
58 | | * HIT (base16). |
59 | | */ |
60 | 3.53k | start = isc_buffer_used(target); |
61 | 3.53k | RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, |
62 | 3.53k | false)); |
63 | 3.52k | RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target)); |
64 | | |
65 | | /* |
66 | | * Fill in HIT len. |
67 | | */ |
68 | 3.49k | len = (unsigned char *)isc_buffer_used(target) - start; |
69 | 3.49k | if (len > 0xffU) { |
70 | 2 | RETTOK(ISC_R_RANGE); |
71 | 2 | } |
72 | 3.49k | RETERR(uint8_tobuffer((uint32_t)len, &hit_len)); |
73 | | |
74 | | /* |
75 | | * Public key (base64). |
76 | | */ |
77 | 3.49k | start = isc_buffer_used(target); |
78 | 3.49k | RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, |
79 | 3.49k | false)); |
80 | 3.47k | RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target)); |
81 | | |
82 | | /* |
83 | | * Fill in KEY len. |
84 | | */ |
85 | 3.44k | len = (unsigned char *)isc_buffer_used(target) - start; |
86 | 3.44k | if (len > 0xffffU) { |
87 | 0 | RETTOK(ISC_R_RANGE); |
88 | 0 | } |
89 | 3.44k | RETERR(uint16_tobuffer((uint32_t)len, &key_len)); |
90 | | |
91 | 3.44k | if (origin == NULL) { |
92 | 101 | origin = dns_rootname; |
93 | 101 | } |
94 | | |
95 | | /* |
96 | | * Rendezvous Servers. |
97 | | */ |
98 | 363k | do { |
99 | 363k | RETERR(isc_lex_getmastertoken(lexer, &token, |
100 | 363k | isc_tokentype_string, true)); |
101 | 363k | if (token.type != isc_tokentype_string) { |
102 | 3.36k | break; |
103 | 3.36k | } |
104 | 359k | buffer_fromregion(&buffer, &token.value.as_region); |
105 | 359k | RETTOK(dns_name_wirefromtext(&buffer, origin, options, target)); |
106 | 359k | } while (1); |
107 | | |
108 | | /* |
109 | | * Let upper layer handle eol/eof. |
110 | | */ |
111 | 3.36k | isc_lex_ungettoken(lexer, &token); |
112 | | |
113 | 3.36k | return ISC_R_SUCCESS; |
114 | 3.44k | } |
115 | | |
116 | | static isc_result_t |
117 | 7.02k | totext_hip(ARGS_TOTEXT) { |
118 | 7.02k | isc_region_t region; |
119 | 7.02k | dns_name_t name; |
120 | 7.02k | unsigned int length, key_len, hit_len; |
121 | 7.02k | unsigned char algorithm; |
122 | 7.02k | char buf[sizeof("225 ")]; |
123 | | |
124 | 7.02k | REQUIRE(rdata->type == dns_rdatatype_hip); |
125 | 7.02k | REQUIRE(rdata->length != 0); |
126 | | |
127 | 7.02k | dns_rdata_toregion(rdata, ®ion); |
128 | | |
129 | 7.02k | hit_len = uint8_fromregion(®ion); |
130 | 7.02k | isc_region_consume(®ion, 1); |
131 | | |
132 | 7.02k | algorithm = uint8_fromregion(®ion); |
133 | 7.02k | isc_region_consume(®ion, 1); |
134 | | |
135 | 7.02k | key_len = uint16_fromregion(®ion); |
136 | 7.02k | isc_region_consume(®ion, 2); |
137 | | |
138 | 7.02k | if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { |
139 | 106 | RETERR(str_totext("( ", target)); |
140 | 106 | } |
141 | | |
142 | | /* |
143 | | * Algorithm |
144 | | */ |
145 | 7.02k | snprintf(buf, sizeof(buf), "%u ", algorithm); |
146 | 7.02k | RETERR(str_totext(buf, target)); |
147 | | |
148 | | /* |
149 | | * HIT. |
150 | | */ |
151 | 7.02k | INSIST(hit_len < region.length); |
152 | 7.02k | length = region.length; |
153 | 7.02k | region.length = hit_len; |
154 | 7.02k | RETERR(isc_hex_totext(®ion, 1, "", target)); |
155 | 7.02k | region.length = length - hit_len; |
156 | 7.02k | RETERR(str_totext(tctx->linebreak, target)); |
157 | | |
158 | | /* |
159 | | * Public KEY. |
160 | | */ |
161 | 7.02k | INSIST(key_len <= region.length); |
162 | 7.02k | length = region.length; |
163 | 7.02k | region.length = key_len; |
164 | 7.02k | RETERR(isc_base64_totext(®ion, 1, "", target)); |
165 | 7.02k | region.length = length - key_len; |
166 | 7.02k | if (region.length > 0) { |
167 | 6.90k | RETERR(str_totext(tctx->linebreak, target)); |
168 | 6.90k | } |
169 | | |
170 | | /* |
171 | | * Rendezvous Servers. |
172 | | */ |
173 | 7.02k | dns_name_init(&name); |
174 | 441k | while (region.length > 0) { |
175 | 434k | dns_name_fromregion(&name, ®ion); |
176 | | |
177 | 434k | RETERR(dns_name_totext(&name, 0, target)); |
178 | 434k | isc_region_consume(®ion, name.length); |
179 | 434k | if (region.length > 0) { |
180 | 428k | RETERR(str_totext(tctx->linebreak, target)); |
181 | 428k | } |
182 | 434k | } |
183 | 7.02k | if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { |
184 | 106 | RETERR(str_totext(" )", target)); |
185 | 106 | } |
186 | 7.02k | return ISC_R_SUCCESS; |
187 | 7.02k | } |
188 | | |
189 | | static isc_result_t |
190 | 38.5k | fromwire_hip(ARGS_FROMWIRE) { |
191 | 38.5k | isc_region_t region, rr; |
192 | 38.5k | dns_name_t name; |
193 | 38.5k | uint8_t hit_len; |
194 | 38.5k | uint16_t key_len; |
195 | 38.5k | size_t len; |
196 | | |
197 | 38.5k | REQUIRE(type == dns_rdatatype_hip); |
198 | | |
199 | 38.5k | UNUSED(type); |
200 | 38.5k | UNUSED(rdclass); |
201 | | |
202 | 38.5k | isc_buffer_activeregion(source, ®ion); |
203 | 38.5k | if (region.length < 4U) { |
204 | 15 | RETERR(DNS_R_FORMERR); |
205 | 15 | } |
206 | | |
207 | 38.5k | rr = region; |
208 | 38.5k | hit_len = uint8_fromregion(®ion); |
209 | 38.5k | if (hit_len == 0) { |
210 | 7 | RETERR(DNS_R_FORMERR); |
211 | 7 | } |
212 | 38.5k | isc_region_consume(®ion, 2); /* hit length + algorithm */ |
213 | 38.5k | key_len = uint16_fromregion(®ion); |
214 | 38.5k | if (key_len == 0) { |
215 | 5 | RETERR(DNS_R_FORMERR); |
216 | 5 | } |
217 | 38.5k | isc_region_consume(®ion, 2); |
218 | 38.5k | len = hit_len + key_len; |
219 | 38.5k | if (len > region.length) { |
220 | 75 | RETERR(DNS_R_FORMERR); |
221 | 75 | } |
222 | | |
223 | 38.4k | RETERR(mem_tobuffer(target, rr.base, 4 + len)); |
224 | 38.2k | isc_buffer_forward(source, 4 + len); |
225 | | |
226 | 38.2k | dctx = dns_decompress_setpermitted(dctx, false); |
227 | 1.17M | while (isc_buffer_activelength(source) > 0) { |
228 | 1.16M | dns_name_init(&name); |
229 | 1.16M | RETERR(dns_name_fromwire(&name, source, dctx, target)); |
230 | 1.16M | } |
231 | 15.6k | return ISC_R_SUCCESS; |
232 | 38.2k | } |
233 | | |
234 | | static isc_result_t |
235 | 3.31k | towire_hip(ARGS_TOWIRE) { |
236 | 3.31k | isc_region_t region; |
237 | | |
238 | 3.31k | REQUIRE(rdata->type == dns_rdatatype_hip); |
239 | 3.31k | REQUIRE(rdata->length != 0); |
240 | | |
241 | 3.31k | UNUSED(cctx); |
242 | | |
243 | 3.31k | dns_rdata_toregion(rdata, ®ion); |
244 | 3.31k | return mem_tobuffer(target, region.base, region.length); |
245 | 3.31k | } |
246 | | |
247 | | static int |
248 | 16.0k | compare_hip(ARGS_COMPARE) { |
249 | 16.0k | isc_region_t region1; |
250 | 16.0k | isc_region_t region2; |
251 | | |
252 | 16.0k | REQUIRE(rdata1->type == rdata2->type); |
253 | 16.0k | REQUIRE(rdata1->rdclass == rdata2->rdclass); |
254 | 16.0k | REQUIRE(rdata1->type == dns_rdatatype_hip); |
255 | 16.0k | REQUIRE(rdata1->length != 0); |
256 | 16.0k | REQUIRE(rdata2->length != 0); |
257 | | |
258 | 16.0k | dns_rdata_toregion(rdata1, ®ion1); |
259 | 16.0k | dns_rdata_toregion(rdata2, ®ion2); |
260 | 16.0k | return isc_region_compare(®ion1, ®ion2); |
261 | 16.0k | } |
262 | | |
263 | | static isc_result_t |
264 | 0 | fromstruct_hip(ARGS_FROMSTRUCT) { |
265 | 0 | dns_rdata_hip_t *hip = source; |
266 | 0 | dns_rdata_hip_t myhip; |
267 | 0 | isc_result_t result; |
268 | |
|
269 | 0 | REQUIRE(type == dns_rdatatype_hip); |
270 | 0 | REQUIRE(hip != NULL); |
271 | 0 | REQUIRE(hip->common.rdtype == type); |
272 | 0 | REQUIRE(hip->common.rdclass == rdclass); |
273 | 0 | REQUIRE(hip->hit_len > 0 && hip->hit != NULL); |
274 | 0 | REQUIRE(hip->key_len > 0 && hip->key != NULL); |
275 | 0 | REQUIRE((hip->servers == NULL && hip->servers_len == 0) || |
276 | 0 | (hip->servers != NULL && hip->servers_len != 0)); |
277 | |
|
278 | 0 | UNUSED(type); |
279 | 0 | UNUSED(rdclass); |
280 | |
|
281 | 0 | RETERR(uint8_tobuffer(hip->hit_len, target)); |
282 | 0 | RETERR(uint8_tobuffer(hip->algorithm, target)); |
283 | 0 | RETERR(uint16_tobuffer(hip->key_len, target)); |
284 | 0 | RETERR(mem_tobuffer(target, hip->hit, hip->hit_len)); |
285 | 0 | RETERR(mem_tobuffer(target, hip->key, hip->key_len)); |
286 | | |
287 | 0 | myhip = *hip; |
288 | 0 | for (result = dns_rdata_hip_first(&myhip); result == ISC_R_SUCCESS; |
289 | 0 | result = dns_rdata_hip_next(&myhip)) |
290 | 0 | { |
291 | | /* initialize the names */ |
292 | 0 | } |
293 | |
|
294 | 0 | return mem_tobuffer(target, hip->servers, hip->servers_len); |
295 | 0 | } |
296 | | |
297 | | static isc_result_t |
298 | 0 | tostruct_hip(ARGS_TOSTRUCT) { |
299 | 0 | isc_region_t region; |
300 | 0 | dns_rdata_hip_t *hip = target; |
301 | |
|
302 | 0 | REQUIRE(rdata->type == dns_rdatatype_hip); |
303 | 0 | REQUIRE(hip != NULL); |
304 | 0 | REQUIRE(rdata->length != 0); |
305 | |
|
306 | 0 | hip->common.rdclass = rdata->rdclass; |
307 | 0 | hip->common.rdtype = rdata->type; |
308 | |
|
309 | 0 | dns_rdata_toregion(rdata, ®ion); |
310 | |
|
311 | 0 | hip->hit_len = uint8_fromregion(®ion); |
312 | 0 | isc_region_consume(®ion, 1); |
313 | |
|
314 | 0 | hip->algorithm = uint8_fromregion(®ion); |
315 | 0 | isc_region_consume(®ion, 1); |
316 | |
|
317 | 0 | hip->key_len = uint16_fromregion(®ion); |
318 | 0 | isc_region_consume(®ion, 2); |
319 | |
|
320 | 0 | hip->hit = hip->key = hip->servers = NULL; |
321 | |
|
322 | 0 | hip->hit = mem_maybedup(mctx, region.base, hip->hit_len); |
323 | 0 | isc_region_consume(®ion, hip->hit_len); |
324 | |
|
325 | 0 | INSIST(hip->key_len <= region.length); |
326 | |
|
327 | 0 | hip->key = mem_maybedup(mctx, region.base, hip->key_len); |
328 | 0 | isc_region_consume(®ion, hip->key_len); |
329 | |
|
330 | 0 | hip->servers_len = region.length; |
331 | 0 | if (hip->servers_len != 0) { |
332 | 0 | hip->servers = mem_maybedup(mctx, region.base, region.length); |
333 | 0 | } |
334 | |
|
335 | 0 | hip->offset = hip->servers_len; |
336 | 0 | hip->mctx = mctx; |
337 | 0 | return ISC_R_SUCCESS; |
338 | 0 | } |
339 | | |
340 | | static void |
341 | 0 | freestruct_hip(ARGS_FREESTRUCT) { |
342 | 0 | dns_rdata_hip_t *hip = source; |
343 | |
|
344 | 0 | REQUIRE(hip != NULL); |
345 | |
|
346 | 0 | if (hip->mctx == NULL) { |
347 | 0 | return; |
348 | 0 | } |
349 | | |
350 | 0 | isc_mem_free(hip->mctx, hip->hit); |
351 | 0 | isc_mem_free(hip->mctx, hip->key); |
352 | 0 | if (hip->servers != NULL) { |
353 | 0 | isc_mem_free(hip->mctx, hip->servers); |
354 | 0 | } |
355 | 0 | hip->mctx = NULL; |
356 | 0 | } |
357 | | |
358 | | static isc_result_t |
359 | 0 | additionaldata_hip(ARGS_ADDLDATA) { |
360 | 0 | REQUIRE(rdata->type == dns_rdatatype_hip); |
361 | |
|
362 | 0 | UNUSED(rdata); |
363 | 0 | UNUSED(owner); |
364 | 0 | UNUSED(add); |
365 | 0 | UNUSED(arg); |
366 | |
|
367 | 0 | return ISC_R_SUCCESS; |
368 | 0 | } |
369 | | |
370 | | static isc_result_t |
371 | 0 | digest_hip(ARGS_DIGEST) { |
372 | 0 | isc_region_t r; |
373 | |
|
374 | 0 | REQUIRE(rdata->type == dns_rdatatype_hip); |
375 | |
|
376 | 0 | dns_rdata_toregion(rdata, &r); |
377 | 0 | return (digest)(arg, &r); |
378 | 0 | } |
379 | | |
380 | | static bool |
381 | 0 | checkowner_hip(ARGS_CHECKOWNER) { |
382 | 0 | REQUIRE(type == dns_rdatatype_hip); |
383 | |
|
384 | 0 | UNUSED(name); |
385 | 0 | UNUSED(type); |
386 | 0 | UNUSED(rdclass); |
387 | 0 | UNUSED(wildcard); |
388 | |
|
389 | 0 | return true; |
390 | 0 | } |
391 | | |
392 | | static bool |
393 | 0 | checknames_hip(ARGS_CHECKNAMES) { |
394 | 0 | REQUIRE(rdata->type == dns_rdatatype_hip); |
395 | |
|
396 | 0 | UNUSED(rdata); |
397 | 0 | UNUSED(owner); |
398 | 0 | UNUSED(bad); |
399 | |
|
400 | 0 | return true; |
401 | 0 | } |
402 | | |
403 | | isc_result_t |
404 | 0 | dns_rdata_hip_first(dns_rdata_hip_t *hip) { |
405 | 0 | if (hip->servers_len == 0) { |
406 | 0 | return ISC_R_NOMORE; |
407 | 0 | } |
408 | 0 | hip->offset = 0; |
409 | 0 | return ISC_R_SUCCESS; |
410 | 0 | } |
411 | | |
412 | | isc_result_t |
413 | 0 | dns_rdata_hip_next(dns_rdata_hip_t *hip) { |
414 | 0 | isc_region_t region; |
415 | 0 | dns_name_t name; |
416 | |
|
417 | 0 | if (hip->offset >= hip->servers_len) { |
418 | 0 | return ISC_R_NOMORE; |
419 | 0 | } |
420 | | |
421 | 0 | region.base = hip->servers + hip->offset; |
422 | 0 | region.length = hip->servers_len - hip->offset; |
423 | 0 | dns_name_init(&name); |
424 | 0 | dns_name_fromregion(&name, ®ion); |
425 | 0 | hip->offset += name.length; |
426 | 0 | INSIST(hip->offset <= hip->servers_len); |
427 | 0 | return hip->offset < hip->servers_len ? ISC_R_SUCCESS : ISC_R_NOMORE; |
428 | 0 | } |
429 | | |
430 | | void |
431 | 0 | dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) { |
432 | 0 | isc_region_t region; |
433 | |
|
434 | 0 | REQUIRE(hip->offset < hip->servers_len); |
435 | |
|
436 | 0 | region.base = hip->servers + hip->offset; |
437 | 0 | region.length = hip->servers_len - hip->offset; |
438 | 0 | dns_name_fromregion(name, ®ion); |
439 | |
|
440 | 0 | INSIST(name->length + hip->offset <= hip->servers_len); |
441 | 0 | } |
442 | | |
443 | | static int |
444 | 0 | casecompare_hip(ARGS_COMPARE) { |
445 | 0 | isc_region_t r1; |
446 | 0 | isc_region_t r2; |
447 | 0 | dns_name_t name1; |
448 | 0 | dns_name_t name2; |
449 | 0 | int order; |
450 | 0 | uint8_t hit_len; |
451 | 0 | uint16_t key_len; |
452 | |
|
453 | 0 | REQUIRE(rdata1->type == rdata2->type); |
454 | 0 | REQUIRE(rdata1->rdclass == rdata2->rdclass); |
455 | 0 | REQUIRE(rdata1->type == dns_rdatatype_hip); |
456 | 0 | REQUIRE(rdata1->length != 0); |
457 | 0 | REQUIRE(rdata2->length != 0); |
458 | |
|
459 | 0 | dns_rdata_toregion(rdata1, &r1); |
460 | 0 | dns_rdata_toregion(rdata2, &r2); |
461 | |
|
462 | 0 | INSIST(r1.length > 4); |
463 | 0 | INSIST(r2.length > 4); |
464 | 0 | order = memcmp(r1.base, r2.base, 4); |
465 | 0 | if (order != 0) { |
466 | 0 | return order; |
467 | 0 | } |
468 | | |
469 | 0 | hit_len = uint8_fromregion(&r1); |
470 | 0 | isc_region_consume(&r1, 2); /* hit length + algorithm */ |
471 | 0 | key_len = uint16_fromregion(&r1); |
472 | 0 | isc_region_consume(&r1, 2); /* key length */ |
473 | 0 | isc_region_consume(&r2, 4); |
474 | |
|
475 | 0 | INSIST(r1.length >= (unsigned int)(hit_len + key_len)); |
476 | 0 | INSIST(r2.length >= (unsigned int)(hit_len + key_len)); |
477 | 0 | order = memcmp(r1.base, r2.base, hit_len + key_len); |
478 | 0 | if (order != 0) { |
479 | 0 | return order; |
480 | 0 | } |
481 | 0 | isc_region_consume(&r1, hit_len + key_len); |
482 | 0 | isc_region_consume(&r2, hit_len + key_len); |
483 | |
|
484 | 0 | dns_name_init(&name1); |
485 | 0 | dns_name_init(&name2); |
486 | 0 | while (r1.length != 0 && r2.length != 0) { |
487 | 0 | dns_name_fromregion(&name1, &r1); |
488 | 0 | dns_name_fromregion(&name2, &r2); |
489 | 0 | order = dns_name_rdatacompare(&name1, &name2); |
490 | 0 | if (order != 0) { |
491 | 0 | return order; |
492 | 0 | } |
493 | | |
494 | 0 | isc_region_consume(&r1, name_length(&name1)); |
495 | 0 | isc_region_consume(&r2, name_length(&name2)); |
496 | 0 | } |
497 | 0 | return isc_region_compare(&r1, &r2); |
498 | 0 | } |