1 /* $NetBSD: tkey_249.c,v 1.8 2023/01/25 21:43:30 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 /* draft-ietf-dnsext-tkey-01.txt */
17
18 #ifndef RDATA_GENERIC_TKEY_249_C
19 #define RDATA_GENERIC_TKEY_249_C
20
21 #define RRTYPE_TKEY_ATTRIBUTES (DNS_RDATATYPEATTR_META)
22
23 static isc_result_t
fromtext_tkey(ARGS_FROMTEXT)24 fromtext_tkey(ARGS_FROMTEXT) {
25 isc_token_t token;
26 dns_rcode_t rcode;
27 dns_name_t name;
28 isc_buffer_t buffer;
29 long i;
30 char *e;
31
32 REQUIRE(type == dns_rdatatype_tkey);
33
34 UNUSED(type);
35 UNUSED(rdclass);
36 UNUSED(callbacks);
37
38 /*
39 * Algorithm.
40 */
41 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
42 false));
43 dns_name_init(&name, NULL);
44 buffer_fromregion(&buffer, &token.value.as_region);
45 if (origin == NULL) {
46 origin = dns_rootname;
47 }
48 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
49
50 /*
51 * Inception.
52 */
53 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
54 false));
55 RETERR(uint32_tobuffer(token.value.as_ulong, target));
56
57 /*
58 * Expiration.
59 */
60 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
61 false));
62 RETERR(uint32_tobuffer(token.value.as_ulong, target));
63
64 /*
65 * Mode.
66 */
67 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
68 false));
69 if (token.value.as_ulong > 0xffffU) {
70 RETTOK(ISC_R_RANGE);
71 }
72 RETERR(uint16_tobuffer(token.value.as_ulong, target));
73
74 /*
75 * Error.
76 */
77 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
78 false));
79 if (dns_tsigrcode_fromtext(&rcode, &token.value.as_textregion) !=
80 ISC_R_SUCCESS)
81 {
82 i = strtol(DNS_AS_STR(token), &e, 10);
83 if (*e != 0) {
84 RETTOK(DNS_R_UNKNOWN);
85 }
86 if (i < 0 || i > 0xffff) {
87 RETTOK(ISC_R_RANGE);
88 }
89 rcode = (dns_rcode_t)i;
90 }
91 RETERR(uint16_tobuffer(rcode, target));
92
93 /*
94 * Key Size.
95 */
96 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
97 false));
98 if (token.value.as_ulong > 0xffffU) {
99 RETTOK(ISC_R_RANGE);
100 }
101 RETERR(uint16_tobuffer(token.value.as_ulong, target));
102
103 /*
104 * Key Data.
105 */
106 RETERR(isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
107
108 /*
109 * Other Size.
110 */
111 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
112 false));
113 if (token.value.as_ulong > 0xffffU) {
114 RETTOK(ISC_R_RANGE);
115 }
116 RETERR(uint16_tobuffer(token.value.as_ulong, target));
117
118 /*
119 * Other Data.
120 */
121 return (isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
122 }
123
124 static isc_result_t
totext_tkey(ARGS_TOTEXT)125 totext_tkey(ARGS_TOTEXT) {
126 isc_region_t sr, dr;
127 char buf[sizeof("4294967295 ")];
128 unsigned long n;
129 dns_name_t name;
130 dns_name_t prefix;
131 bool sub;
132
133 REQUIRE(rdata->type == dns_rdatatype_tkey);
134 REQUIRE(rdata->length != 0);
135
136 dns_rdata_toregion(rdata, &sr);
137
138 /*
139 * Algorithm.
140 */
141 dns_name_init(&name, NULL);
142 dns_name_init(&prefix, NULL);
143 dns_name_fromregion(&name, &sr);
144 sub = name_prefix(&name, tctx->origin, &prefix);
145 RETERR(dns_name_totext(&prefix, sub, target));
146 RETERR(str_totext(" ", target));
147 isc_region_consume(&sr, name_length(&name));
148
149 /*
150 * Inception.
151 */
152 n = uint32_fromregion(&sr);
153 isc_region_consume(&sr, 4);
154 snprintf(buf, sizeof(buf), "%lu ", n);
155 RETERR(str_totext(buf, target));
156
157 /*
158 * Expiration.
159 */
160 n = uint32_fromregion(&sr);
161 isc_region_consume(&sr, 4);
162 snprintf(buf, sizeof(buf), "%lu ", n);
163 RETERR(str_totext(buf, target));
164
165 /*
166 * Mode.
167 */
168 n = uint16_fromregion(&sr);
169 isc_region_consume(&sr, 2);
170 snprintf(buf, sizeof(buf), "%lu ", n);
171 RETERR(str_totext(buf, target));
172
173 /*
174 * Error.
175 */
176 n = uint16_fromregion(&sr);
177 isc_region_consume(&sr, 2);
178 if (dns_tsigrcode_totext((dns_rcode_t)n, target) == ISC_R_SUCCESS) {
179 RETERR(str_totext(" ", target));
180 } else {
181 snprintf(buf, sizeof(buf), "%lu ", n);
182 RETERR(str_totext(buf, target));
183 }
184
185 /*
186 * Key Size.
187 */
188 n = uint16_fromregion(&sr);
189 isc_region_consume(&sr, 2);
190 snprintf(buf, sizeof(buf), "%lu", n);
191 RETERR(str_totext(buf, target));
192
193 /*
194 * Key Data.
195 */
196 REQUIRE(n <= sr.length);
197 dr = sr;
198 dr.length = n;
199 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
200 RETERR(str_totext(" (", target));
201 }
202 RETERR(str_totext(tctx->linebreak, target));
203 if (tctx->width == 0) { /* No splitting */
204 RETERR(isc_base64_totext(&dr, 60, "", target));
205 } else {
206 RETERR(isc_base64_totext(&dr, tctx->width - 2, tctx->linebreak,
207 target));
208 }
209 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
210 RETERR(str_totext(" ) ", target));
211 } else {
212 RETERR(str_totext(" ", target));
213 }
214 isc_region_consume(&sr, n);
215
216 /*
217 * Other Size.
218 */
219 n = uint16_fromregion(&sr);
220 isc_region_consume(&sr, 2);
221 snprintf(buf, sizeof(buf), "%lu", n);
222 RETERR(str_totext(buf, target));
223
224 /*
225 * Other Data.
226 */
227 REQUIRE(n <= sr.length);
228 if (n != 0U) {
229 dr = sr;
230 dr.length = n;
231 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
232 RETERR(str_totext(" (", target));
233 }
234 RETERR(str_totext(tctx->linebreak, target));
235 if (tctx->width == 0) { /* No splitting */
236 RETERR(isc_base64_totext(&dr, 60, "", target));
237 } else {
238 RETERR(isc_base64_totext(&dr, tctx->width - 2,
239 tctx->linebreak, target));
240 }
241 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
242 RETERR(str_totext(" )", target));
243 }
244 }
245 return (ISC_R_SUCCESS);
246 }
247
248 static isc_result_t
fromwire_tkey(ARGS_FROMWIRE)249 fromwire_tkey(ARGS_FROMWIRE) {
250 isc_region_t sr;
251 unsigned long n;
252 dns_name_t name;
253
254 REQUIRE(type == dns_rdatatype_tkey);
255
256 UNUSED(type);
257 UNUSED(rdclass);
258
259 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
260
261 /*
262 * Algorithm.
263 */
264 dns_name_init(&name, NULL);
265 RETERR(dns_name_fromwire(&name, source, dctx, options, target));
266
267 /*
268 * Inception: 4
269 * Expiration: 4
270 * Mode: 2
271 * Error: 2
272 */
273 isc_buffer_activeregion(source, &sr);
274 if (sr.length < 12) {
275 return (ISC_R_UNEXPECTEDEND);
276 }
277 RETERR(mem_tobuffer(target, sr.base, 12));
278 isc_region_consume(&sr, 12);
279 isc_buffer_forward(source, 12);
280
281 /*
282 * Key Length + Key Data.
283 */
284 if (sr.length < 2) {
285 return (ISC_R_UNEXPECTEDEND);
286 }
287 n = uint16_fromregion(&sr);
288 if (sr.length < n + 2) {
289 return (ISC_R_UNEXPECTEDEND);
290 }
291 RETERR(mem_tobuffer(target, sr.base, n + 2));
292 isc_region_consume(&sr, n + 2);
293 isc_buffer_forward(source, n + 2);
294
295 /*
296 * Other Length + Other Data.
297 */
298 if (sr.length < 2) {
299 return (ISC_R_UNEXPECTEDEND);
300 }
301 n = uint16_fromregion(&sr);
302 if (sr.length < n + 2) {
303 return (ISC_R_UNEXPECTEDEND);
304 }
305 isc_buffer_forward(source, n + 2);
306 return (mem_tobuffer(target, sr.base, n + 2));
307 }
308
309 static isc_result_t
towire_tkey(ARGS_TOWIRE)310 towire_tkey(ARGS_TOWIRE) {
311 isc_region_t sr;
312 dns_name_t name;
313 dns_offsets_t offsets;
314
315 REQUIRE(rdata->type == dns_rdatatype_tkey);
316 REQUIRE(rdata->length != 0);
317
318 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
319 /*
320 * Algorithm.
321 */
322 dns_rdata_toregion(rdata, &sr);
323 dns_name_init(&name, offsets);
324 dns_name_fromregion(&name, &sr);
325 RETERR(dns_name_towire(&name, cctx, target));
326 isc_region_consume(&sr, name_length(&name));
327
328 return (mem_tobuffer(target, sr.base, sr.length));
329 }
330
331 static int
compare_tkey(ARGS_COMPARE)332 compare_tkey(ARGS_COMPARE) {
333 isc_region_t r1;
334 isc_region_t r2;
335 dns_name_t name1;
336 dns_name_t name2;
337 int order;
338
339 REQUIRE(rdata1->type == rdata2->type);
340 REQUIRE(rdata1->rdclass == rdata2->rdclass);
341 REQUIRE(rdata1->type == dns_rdatatype_tkey);
342 REQUIRE(rdata1->length != 0);
343 REQUIRE(rdata2->length != 0);
344
345 /*
346 * Algorithm.
347 */
348 dns_rdata_toregion(rdata1, &r1);
349 dns_rdata_toregion(rdata2, &r2);
350 dns_name_init(&name1, NULL);
351 dns_name_init(&name2, NULL);
352 dns_name_fromregion(&name1, &r1);
353 dns_name_fromregion(&name2, &r2);
354 if ((order = dns_name_rdatacompare(&name1, &name2)) != 0) {
355 return (order);
356 }
357 isc_region_consume(&r1, name_length(&name1));
358 isc_region_consume(&r2, name_length(&name2));
359 return (isc_region_compare(&r1, &r2));
360 }
361
362 static isc_result_t
fromstruct_tkey(ARGS_FROMSTRUCT)363 fromstruct_tkey(ARGS_FROMSTRUCT) {
364 dns_rdata_tkey_t *tkey = source;
365
366 REQUIRE(type == dns_rdatatype_tkey);
367 REQUIRE(tkey != NULL);
368 REQUIRE(tkey->common.rdtype == type);
369 REQUIRE(tkey->common.rdclass == rdclass);
370
371 UNUSED(type);
372 UNUSED(rdclass);
373
374 /*
375 * Algorithm Name.
376 */
377 RETERR(name_tobuffer(&tkey->algorithm, target));
378
379 /*
380 * Inception: 32 bits.
381 */
382 RETERR(uint32_tobuffer(tkey->inception, target));
383
384 /*
385 * Expire: 32 bits.
386 */
387 RETERR(uint32_tobuffer(tkey->expire, target));
388
389 /*
390 * Mode: 16 bits.
391 */
392 RETERR(uint16_tobuffer(tkey->mode, target));
393
394 /*
395 * Error: 16 bits.
396 */
397 RETERR(uint16_tobuffer(tkey->error, target));
398
399 /*
400 * Key size: 16 bits.
401 */
402 RETERR(uint16_tobuffer(tkey->keylen, target));
403
404 /*
405 * Key.
406 */
407 RETERR(mem_tobuffer(target, tkey->key, tkey->keylen));
408
409 /*
410 * Other size: 16 bits.
411 */
412 RETERR(uint16_tobuffer(tkey->otherlen, target));
413
414 /*
415 * Other data.
416 */
417 return (mem_tobuffer(target, tkey->other, tkey->otherlen));
418 }
419
420 static isc_result_t
tostruct_tkey(ARGS_TOSTRUCT)421 tostruct_tkey(ARGS_TOSTRUCT) {
422 dns_rdata_tkey_t *tkey = target;
423 dns_name_t alg;
424 isc_region_t sr;
425
426 REQUIRE(rdata->type == dns_rdatatype_tkey);
427 REQUIRE(tkey != NULL);
428 REQUIRE(rdata->length != 0);
429
430 tkey->common.rdclass = rdata->rdclass;
431 tkey->common.rdtype = rdata->type;
432 ISC_LINK_INIT(&tkey->common, link);
433
434 dns_rdata_toregion(rdata, &sr);
435
436 /*
437 * Algorithm Name.
438 */
439 dns_name_init(&alg, NULL);
440 dns_name_fromregion(&alg, &sr);
441 dns_name_init(&tkey->algorithm, NULL);
442 RETERR(name_duporclone(&alg, mctx, &tkey->algorithm));
443 isc_region_consume(&sr, name_length(&tkey->algorithm));
444
445 /*
446 * Inception.
447 */
448 tkey->inception = uint32_fromregion(&sr);
449 isc_region_consume(&sr, 4);
450
451 /*
452 * Expire.
453 */
454 tkey->expire = uint32_fromregion(&sr);
455 isc_region_consume(&sr, 4);
456
457 /*
458 * Mode.
459 */
460 tkey->mode = uint16_fromregion(&sr);
461 isc_region_consume(&sr, 2);
462
463 /*
464 * Error.
465 */
466 tkey->error = uint16_fromregion(&sr);
467 isc_region_consume(&sr, 2);
468
469 /*
470 * Key size.
471 */
472 tkey->keylen = uint16_fromregion(&sr);
473 isc_region_consume(&sr, 2);
474
475 /*
476 * Key.
477 */
478 INSIST(tkey->keylen + 2U <= sr.length);
479 tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen);
480 if (tkey->key == NULL) {
481 goto cleanup;
482 }
483 isc_region_consume(&sr, tkey->keylen);
484
485 /*
486 * Other size.
487 */
488 tkey->otherlen = uint16_fromregion(&sr);
489 isc_region_consume(&sr, 2);
490
491 /*
492 * Other.
493 */
494 INSIST(tkey->otherlen <= sr.length);
495 tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen);
496 if (tkey->other == NULL) {
497 goto cleanup;
498 }
499
500 tkey->mctx = mctx;
501 return (ISC_R_SUCCESS);
502
503 cleanup:
504 if (mctx != NULL) {
505 dns_name_free(&tkey->algorithm, mctx);
506 }
507 if (mctx != NULL && tkey->key != NULL) {
508 isc_mem_free(mctx, tkey->key);
509 }
510 return (ISC_R_NOMEMORY);
511 }
512
513 static void
freestruct_tkey(ARGS_FREESTRUCT)514 freestruct_tkey(ARGS_FREESTRUCT) {
515 dns_rdata_tkey_t *tkey = (dns_rdata_tkey_t *)source;
516
517 REQUIRE(tkey != NULL);
518
519 if (tkey->mctx == NULL) {
520 return;
521 }
522
523 dns_name_free(&tkey->algorithm, tkey->mctx);
524 if (tkey->key != NULL) {
525 isc_mem_free(tkey->mctx, tkey->key);
526 }
527 if (tkey->other != NULL) {
528 isc_mem_free(tkey->mctx, tkey->other);
529 }
530 tkey->mctx = NULL;
531 }
532
533 static isc_result_t
additionaldata_tkey(ARGS_ADDLDATA)534 additionaldata_tkey(ARGS_ADDLDATA) {
535 UNUSED(rdata);
536 UNUSED(add);
537 UNUSED(arg);
538
539 REQUIRE(rdata->type == dns_rdatatype_tkey);
540
541 return (ISC_R_SUCCESS);
542 }
543
544 static isc_result_t
digest_tkey(ARGS_DIGEST)545 digest_tkey(ARGS_DIGEST) {
546 UNUSED(rdata);
547 UNUSED(digest);
548 UNUSED(arg);
549
550 REQUIRE(rdata->type == dns_rdatatype_tkey);
551
552 return (ISC_R_NOTIMPLEMENTED);
553 }
554
555 static bool
checkowner_tkey(ARGS_CHECKOWNER)556 checkowner_tkey(ARGS_CHECKOWNER) {
557 REQUIRE(type == dns_rdatatype_tkey);
558
559 UNUSED(name);
560 UNUSED(type);
561 UNUSED(rdclass);
562 UNUSED(wildcard);
563
564 return (true);
565 }
566
567 static bool
checknames_tkey(ARGS_CHECKNAMES)568 checknames_tkey(ARGS_CHECKNAMES) {
569 REQUIRE(rdata->type == dns_rdatatype_tkey);
570
571 UNUSED(rdata);
572 UNUSED(owner);
573 UNUSED(bad);
574
575 return (true);
576 }
577
578 static int
casecompare_tkey(ARGS_COMPARE)579 casecompare_tkey(ARGS_COMPARE) {
580 return (compare_tkey(rdata1, rdata2));
581 }
582 #endif /* RDATA_GENERIC_TKEY_249_C */
583