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