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