1 /* $NetBSD: caa_257.c,v 1.1 2024/02/18 20:57:40 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 #ifndef GENERIC_CAA_257_C
17 #define GENERIC_CAA_257_C 1
18
19 #define RRTYPE_CAA_ATTRIBUTES (0)
20
21 static unsigned char const alphanumeric[256] = {
22 /* 0x00-0x0f */ 0,
23 0,
24 0,
25 0,
26 0,
27 0,
28 0,
29 0,
30 0,
31 0,
32 0,
33 0,
34 0,
35 0,
36 0,
37 0,
38 /* 0x10-0x1f */ 0,
39 0,
40 0,
41 0,
42 0,
43 0,
44 0,
45 0,
46 0,
47 0,
48 0,
49 0,
50 0,
51 0,
52 0,
53 0,
54 /* 0x20-0x2f */ 0,
55 0,
56 0,
57 0,
58 0,
59 0,
60 0,
61 0,
62 0,
63 0,
64 0,
65 0,
66 0,
67 0,
68 0,
69 0,
70 /* 0x30-0x3f */ 1,
71 1,
72 1,
73 1,
74 1,
75 1,
76 1,
77 1,
78 1,
79 1,
80 0,
81 0,
82 0,
83 0,
84 0,
85 0,
86 /* 0x40-0x4f */ 0,
87 1,
88 1,
89 1,
90 1,
91 1,
92 1,
93 1,
94 1,
95 1,
96 1,
97 1,
98 1,
99 1,
100 1,
101 1,
102 /* 0x50-0x5f */ 1,
103 1,
104 1,
105 1,
106 1,
107 1,
108 1,
109 1,
110 1,
111 1,
112 1,
113 0,
114 0,
115 0,
116 0,
117 0,
118 /* 0x60-0x6f */ 0,
119 1,
120 1,
121 1,
122 1,
123 1,
124 1,
125 1,
126 1,
127 1,
128 1,
129 1,
130 1,
131 1,
132 1,
133 1,
134 /* 0x70-0x7f */ 1,
135 1,
136 1,
137 1,
138 1,
139 1,
140 1,
141 1,
142 1,
143 1,
144 1,
145 0,
146 0,
147 0,
148 0,
149 0,
150 /* 0x80-0x8f */ 0,
151 0,
152 0,
153 0,
154 0,
155 0,
156 0,
157 0,
158 0,
159 0,
160 0,
161 0,
162 0,
163 0,
164 0,
165 0,
166 /* 0x90-0x9f */ 0,
167 0,
168 0,
169 0,
170 0,
171 0,
172 0,
173 0,
174 0,
175 0,
176 0,
177 0,
178 0,
179 0,
180 0,
181 0,
182 /* 0xa0-0xaf */ 0,
183 0,
184 0,
185 0,
186 0,
187 0,
188 0,
189 0,
190 0,
191 0,
192 0,
193 0,
194 0,
195 0,
196 0,
197 0,
198 /* 0xb0-0xbf */ 0,
199 0,
200 0,
201 0,
202 0,
203 0,
204 0,
205 0,
206 0,
207 0,
208 0,
209 0,
210 0,
211 0,
212 0,
213 0,
214 /* 0xc0-0xcf */ 0,
215 0,
216 0,
217 0,
218 0,
219 0,
220 0,
221 0,
222 0,
223 0,
224 0,
225 0,
226 0,
227 0,
228 0,
229 0,
230 /* 0xd0-0xdf */ 0,
231 0,
232 0,
233 0,
234 0,
235 0,
236 0,
237 0,
238 0,
239 0,
240 0,
241 0,
242 0,
243 0,
244 0,
245 0,
246 /* 0xe0-0xef */ 0,
247 0,
248 0,
249 0,
250 0,
251 0,
252 0,
253 0,
254 0,
255 0,
256 0,
257 0,
258 0,
259 0,
260 0,
261 0,
262 /* 0xf0-0xff */ 0,
263 0,
264 0,
265 0,
266 0,
267 0,
268 0,
269 0,
270 0,
271 0,
272 0,
273 0,
274 0,
275 0,
276 0,
277 0,
278 };
279
280 static isc_result_t
fromtext_caa(ARGS_FROMTEXT)281 fromtext_caa(ARGS_FROMTEXT) {
282 isc_token_t token;
283 isc_textregion_t tr;
284 uint8_t flags;
285 unsigned int i;
286
287 REQUIRE(type == dns_rdatatype_caa);
288
289 UNUSED(type);
290 UNUSED(rdclass);
291 UNUSED(origin);
292 UNUSED(options);
293 UNUSED(callbacks);
294
295 /* Flags. */
296 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
297 false));
298 if (token.value.as_ulong > 255U) {
299 RETTOK(ISC_R_RANGE);
300 }
301 flags = (uint8_t)(token.value.as_ulong & 255U);
302 RETERR(uint8_tobuffer(flags, target));
303
304 /*
305 * Tag
306 */
307 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
308 false));
309 tr = token.value.as_textregion;
310 for (i = 0; i < tr.length; i++) {
311 if (!alphanumeric[(unsigned char)tr.base[i]]) {
312 RETTOK(DNS_R_SYNTAX);
313 }
314 }
315 RETERR(uint8_tobuffer(tr.length, target));
316 RETERR(mem_tobuffer(target, tr.base, tr.length));
317
318 /*
319 * Value
320 */
321 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
322 false));
323 if (token.type != isc_tokentype_qstring &&
324 token.type != isc_tokentype_string)
325 {
326 RETERR(DNS_R_SYNTAX);
327 }
328 RETERR(multitxt_fromtext(&token.value.as_textregion, target));
329 return (ISC_R_SUCCESS);
330 }
331
332 static isc_result_t
totext_caa(ARGS_TOTEXT)333 totext_caa(ARGS_TOTEXT) {
334 isc_region_t region;
335 uint8_t flags;
336 char buf[256];
337
338 UNUSED(tctx);
339
340 REQUIRE(rdata->type == dns_rdatatype_caa);
341 REQUIRE(rdata->length >= 3U);
342 REQUIRE(rdata->data != NULL);
343
344 dns_rdata_toregion(rdata, ®ion);
345
346 /*
347 * Flags
348 */
349 flags = uint8_consume_fromregion(®ion);
350 snprintf(buf, sizeof(buf), "%u ", flags);
351 RETERR(str_totext(buf, target));
352
353 /*
354 * Tag
355 */
356 RETERR(txt_totext(®ion, false, target));
357 RETERR(str_totext(" ", target));
358
359 /*
360 * Value
361 */
362 RETERR(multitxt_totext(®ion, target));
363 return (ISC_R_SUCCESS);
364 }
365
366 static isc_result_t
fromwire_caa(ARGS_FROMWIRE)367 fromwire_caa(ARGS_FROMWIRE) {
368 isc_region_t sr;
369 unsigned int len, i;
370
371 REQUIRE(type == dns_rdatatype_caa);
372
373 UNUSED(type);
374 UNUSED(rdclass);
375 UNUSED(dctx);
376 UNUSED(options);
377
378 /*
379 * Flags
380 */
381 isc_buffer_activeregion(source, &sr);
382 if (sr.length < 2) {
383 return (ISC_R_UNEXPECTEDEND);
384 }
385
386 /*
387 * Flags, tag length
388 */
389 RETERR(mem_tobuffer(target, sr.base, 2));
390 len = sr.base[1];
391 isc_region_consume(&sr, 2);
392 isc_buffer_forward(source, 2);
393
394 /*
395 * Zero length tag fields are illegal.
396 */
397 if (sr.length < len || len == 0) {
398 RETERR(DNS_R_FORMERR);
399 }
400
401 /* Check the Tag's value */
402 for (i = 0; i < len; i++) {
403 if (!alphanumeric[sr.base[i]]) {
404 RETERR(DNS_R_FORMERR);
405 /*
406 * Tag + Value
407 */
408 }
409 }
410 /*
411 * Tag + Value
412 */
413 isc_buffer_forward(source, sr.length);
414 return (mem_tobuffer(target, sr.base, sr.length));
415 }
416
417 static isc_result_t
towire_caa(ARGS_TOWIRE)418 towire_caa(ARGS_TOWIRE) {
419 isc_region_t region;
420
421 REQUIRE(rdata->type == dns_rdatatype_caa);
422 REQUIRE(rdata->length >= 3U);
423 REQUIRE(rdata->data != NULL);
424
425 UNUSED(cctx);
426
427 dns_rdata_toregion(rdata, ®ion);
428 return (mem_tobuffer(target, region.base, region.length));
429 }
430
431 static int
compare_caa(ARGS_COMPARE)432 compare_caa(ARGS_COMPARE) {
433 isc_region_t r1, r2;
434
435 REQUIRE(rdata1->type == rdata2->type);
436 REQUIRE(rdata1->rdclass == rdata2->rdclass);
437 REQUIRE(rdata1->type == dns_rdatatype_caa);
438 REQUIRE(rdata1->length >= 3U);
439 REQUIRE(rdata2->length >= 3U);
440 REQUIRE(rdata1->data != NULL);
441 REQUIRE(rdata2->data != NULL);
442
443 dns_rdata_toregion(rdata1, &r1);
444 dns_rdata_toregion(rdata2, &r2);
445 return (isc_region_compare(&r1, &r2));
446 }
447
448 static isc_result_t
fromstruct_caa(ARGS_FROMSTRUCT)449 fromstruct_caa(ARGS_FROMSTRUCT) {
450 dns_rdata_caa_t *caa = source;
451 isc_region_t region;
452 unsigned int i;
453
454 REQUIRE(type == dns_rdatatype_caa);
455 REQUIRE(caa != NULL);
456 REQUIRE(caa->common.rdtype == type);
457 REQUIRE(caa->common.rdclass == rdclass);
458 REQUIRE(caa->tag != NULL && caa->tag_len != 0);
459 REQUIRE(caa->value != NULL);
460
461 UNUSED(type);
462 UNUSED(rdclass);
463
464 /*
465 * Flags
466 */
467 RETERR(uint8_tobuffer(caa->flags, target));
468
469 /*
470 * Tag length
471 */
472 RETERR(uint8_tobuffer(caa->tag_len, target));
473
474 /*
475 * Tag
476 */
477 region.base = caa->tag;
478 region.length = caa->tag_len;
479 for (i = 0; i < region.length; i++) {
480 if (!alphanumeric[region.base[i]]) {
481 RETERR(DNS_R_SYNTAX);
482 }
483 }
484 RETERR(isc_buffer_copyregion(target, ®ion));
485
486 /*
487 * Value
488 */
489 region.base = caa->value;
490 region.length = caa->value_len;
491 return (isc_buffer_copyregion(target, ®ion));
492 }
493
494 static isc_result_t
tostruct_caa(ARGS_TOSTRUCT)495 tostruct_caa(ARGS_TOSTRUCT) {
496 dns_rdata_caa_t *caa = target;
497 isc_region_t sr;
498
499 REQUIRE(rdata->type == dns_rdatatype_caa);
500 REQUIRE(caa != NULL);
501 REQUIRE(rdata->length >= 3U);
502 REQUIRE(rdata->data != NULL);
503
504 caa->common.rdclass = rdata->rdclass;
505 caa->common.rdtype = rdata->type;
506 ISC_LINK_INIT(&caa->common, link);
507
508 dns_rdata_toregion(rdata, &sr);
509
510 /*
511 * Flags
512 */
513 if (sr.length < 1) {
514 return (ISC_R_UNEXPECTEDEND);
515 }
516 caa->flags = uint8_fromregion(&sr);
517 isc_region_consume(&sr, 1);
518
519 /*
520 * Tag length
521 */
522 if (sr.length < 1) {
523 return (ISC_R_UNEXPECTEDEND);
524 }
525 caa->tag_len = uint8_fromregion(&sr);
526 isc_region_consume(&sr, 1);
527
528 /*
529 * Tag
530 */
531 if (sr.length < caa->tag_len) {
532 return (ISC_R_UNEXPECTEDEND);
533 }
534 caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len);
535 if (caa->tag == NULL) {
536 return (ISC_R_NOMEMORY);
537 }
538 isc_region_consume(&sr, caa->tag_len);
539
540 /*
541 * Value
542 */
543 caa->value_len = sr.length;
544 caa->value = mem_maybedup(mctx, sr.base, sr.length);
545 if (caa->value == NULL) {
546 return (ISC_R_NOMEMORY);
547 }
548
549 caa->mctx = mctx;
550 return (ISC_R_SUCCESS);
551 }
552
553 static void
freestruct_caa(ARGS_FREESTRUCT)554 freestruct_caa(ARGS_FREESTRUCT) {
555 dns_rdata_caa_t *caa = (dns_rdata_caa_t *)source;
556
557 REQUIRE(caa != NULL);
558 REQUIRE(caa->common.rdtype == dns_rdatatype_caa);
559
560 if (caa->mctx == NULL) {
561 return;
562 }
563
564 if (caa->tag != NULL) {
565 isc_mem_free(caa->mctx, caa->tag);
566 }
567 if (caa->value != NULL) {
568 isc_mem_free(caa->mctx, caa->value);
569 }
570 caa->mctx = NULL;
571 }
572
573 static isc_result_t
additionaldata_caa(ARGS_ADDLDATA)574 additionaldata_caa(ARGS_ADDLDATA) {
575 REQUIRE(rdata->type == dns_rdatatype_caa);
576 REQUIRE(rdata->data != NULL);
577 REQUIRE(rdata->length >= 3U);
578
579 UNUSED(rdata);
580 UNUSED(add);
581 UNUSED(arg);
582
583 return (ISC_R_SUCCESS);
584 }
585
586 static isc_result_t
digest_caa(ARGS_DIGEST)587 digest_caa(ARGS_DIGEST) {
588 isc_region_t r;
589
590 REQUIRE(rdata->type == dns_rdatatype_caa);
591 REQUIRE(rdata->data != NULL);
592 REQUIRE(rdata->length >= 3U);
593
594 dns_rdata_toregion(rdata, &r);
595
596 return ((digest)(arg, &r));
597 }
598
599 static bool
checkowner_caa(ARGS_CHECKOWNER)600 checkowner_caa(ARGS_CHECKOWNER) {
601 REQUIRE(type == dns_rdatatype_caa);
602
603 UNUSED(name);
604 UNUSED(type);
605 UNUSED(rdclass);
606 UNUSED(wildcard);
607
608 return (true);
609 }
610
611 static bool
checknames_caa(ARGS_CHECKNAMES)612 checknames_caa(ARGS_CHECKNAMES) {
613 REQUIRE(rdata->type == dns_rdatatype_caa);
614 REQUIRE(rdata->data != NULL);
615 REQUIRE(rdata->length >= 3U);
616
617 UNUSED(rdata);
618 UNUSED(owner);
619 UNUSED(bad);
620
621 return (true);
622 }
623
624 static int
casecompare_caa(ARGS_COMPARE)625 casecompare_caa(ARGS_COMPARE) {
626 return (compare_caa(rdata1, rdata2));
627 }
628
629 #endif /* GENERIC_CAA_257_C */
630