1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /* $Id: tsig_250.c,v 1.10 2020/09/14 08:40:43 florian Exp $ */
18 
19 /* Reviewed: Thu Mar 16 13:39:43 PST 2000 by gson */
20 
21 #ifndef RDATA_ANY_255_TSIG_250_C
22 #define RDATA_ANY_255_TSIG_250_C
23 
24 static inline isc_result_t
totext_any_tsig(ARGS_TOTEXT)25 totext_any_tsig(ARGS_TOTEXT) {
26 	isc_region_t sr;
27 	isc_region_t sigr;
28 	char buf[sizeof(" 281474976710655 ")];
29 	char *bufp;
30 	dns_name_t name;
31 	dns_name_t prefix;
32 	int sub;
33 	uint64_t sigtime;
34 	unsigned short n;
35 
36 	REQUIRE(rdata->type == dns_rdatatype_tsig);
37 	REQUIRE(rdata->rdclass == dns_rdataclass_any);
38 	REQUIRE(rdata->length != 0);
39 
40 	dns_rdata_toregion(rdata, &sr);
41 	/*
42 	 * Algorithm Name.
43 	 */
44 	dns_name_init(&name, NULL);
45 	dns_name_init(&prefix, NULL);
46 	dns_name_fromregion(&name, &sr);
47 	sub = name_prefix(&name, tctx->origin, &prefix);
48 	RETERR(dns_name_totext(&prefix, sub, target));
49 	RETERR(isc_str_tobuffer(" ", target));
50 	isc_region_consume(&sr, name_length(&name));
51 
52 	/*
53 	 * Time Signed.
54 	 */
55 	sigtime = ((uint64_t)sr.base[0] << 40) |
56 		  ((uint64_t)sr.base[1] << 32) |
57 		  ((uint64_t)sr.base[2] << 24) |
58 		  ((uint64_t)sr.base[3] << 16) |
59 		  ((uint64_t)sr.base[4] << 8) |
60 		  (uint64_t)sr.base[5];
61 	isc_region_consume(&sr, 6);
62 	bufp = &buf[sizeof(buf) - 1];
63 	*bufp-- = 0;
64 	*bufp-- = ' ';
65 	do {
66 		*bufp-- = decdigits[sigtime % 10];
67 		sigtime /= 10;
68 	} while (sigtime != 0);
69 	bufp++;
70 	RETERR(isc_str_tobuffer(bufp, target));
71 
72 	/*
73 	 * Fudge.
74 	 */
75 	n = uint16_fromregion(&sr);
76 	isc_region_consume(&sr, 2);
77 	snprintf(buf, sizeof(buf), "%u ", n);
78 	RETERR(isc_str_tobuffer(buf, target));
79 
80 	/*
81 	 * Signature Size.
82 	 */
83 	n = uint16_fromregion(&sr);
84 	isc_region_consume(&sr, 2);
85 	snprintf(buf, sizeof(buf), "%u", n);
86 	RETERR(isc_str_tobuffer(buf, target));
87 
88 	/*
89 	 * Signature.
90 	 */
91 	REQUIRE(n <= sr.length);
92 	sigr = sr;
93 	sigr.length = n;
94 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
95 		RETERR(isc_str_tobuffer(" (", target));
96 	RETERR(isc_str_tobuffer(tctx->linebreak, target));
97 	if (tctx->width == 0)   /* No splitting */
98 		RETERR(isc_base64_totext(&sigr, 60, "", target));
99 	else
100 		RETERR(isc_base64_totext(&sigr, tctx->width - 2,
101 					 tctx->linebreak, target));
102 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
103 		RETERR(isc_str_tobuffer(" ) ", target));
104 	else
105 		RETERR(isc_str_tobuffer(" ", target));
106 	isc_region_consume(&sr, n);
107 
108 	/*
109 	 * Original ID.
110 	 */
111 	n = uint16_fromregion(&sr);
112 	isc_region_consume(&sr, 2);
113 	snprintf(buf, sizeof(buf), "%u ", n);
114 	RETERR(isc_str_tobuffer(buf, target));
115 
116 	/*
117 	 * Error.
118 	 */
119 	n = uint16_fromregion(&sr);
120 	isc_region_consume(&sr, 2);
121 	RETERR(dns_tsigrcode_totext((dns_rcode_t)n, target));
122 
123 	/*
124 	 * Other Size.
125 	 */
126 	n = uint16_fromregion(&sr);
127 	isc_region_consume(&sr, 2);
128 	snprintf(buf, sizeof(buf), " %u ", n);
129 	RETERR(isc_str_tobuffer(buf, target));
130 
131 	/*
132 	 * Other.
133 	 */
134 	if (tctx->width == 0)   /* No splitting */
135 		return (isc_base64_totext(&sr, 60, "", target));
136 	else
137 		return (isc_base64_totext(&sr, 60, " ", target));
138 }
139 
140 static inline isc_result_t
fromwire_any_tsig(ARGS_FROMWIRE)141 fromwire_any_tsig(ARGS_FROMWIRE) {
142 	isc_region_t sr;
143 	dns_name_t name;
144 	unsigned long n;
145 
146 	REQUIRE(type == dns_rdatatype_tsig);
147 	REQUIRE(rdclass == dns_rdataclass_any);
148 
149 	UNUSED(type);
150 	UNUSED(rdclass);
151 
152 	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
153 
154 	/*
155 	 * Algorithm Name.
156 	 */
157 	dns_name_init(&name, NULL);
158 	RETERR(dns_name_fromwire(&name, source, dctx, options, target));
159 
160 	isc_buffer_activeregion(source, &sr);
161 	/*
162 	 * Time Signed + Fudge.
163 	 */
164 	if (sr.length < 8)
165 		return (ISC_R_UNEXPECTEDEND);
166 	RETERR(isc_mem_tobuffer(target, sr.base, 8));
167 	isc_region_consume(&sr, 8);
168 	isc_buffer_forward(source, 8);
169 
170 	/*
171 	 * Signature Length + Signature.
172 	 */
173 	if (sr.length < 2)
174 		return (ISC_R_UNEXPECTEDEND);
175 	n = uint16_fromregion(&sr);
176 	if (sr.length < n + 2)
177 		return (ISC_R_UNEXPECTEDEND);
178 	RETERR(isc_mem_tobuffer(target, sr.base, n + 2));
179 	isc_region_consume(&sr, n + 2);
180 	isc_buffer_forward(source, n + 2);
181 
182 	/*
183 	 * Original ID + Error.
184 	 */
185 	if (sr.length < 4)
186 		return (ISC_R_UNEXPECTEDEND);
187 	RETERR(isc_mem_tobuffer(target, sr.base,  4));
188 	isc_region_consume(&sr, 4);
189 	isc_buffer_forward(source, 4);
190 
191 	/*
192 	 * Other Length + Other.
193 	 */
194 	if (sr.length < 2)
195 		return (ISC_R_UNEXPECTEDEND);
196 	n = uint16_fromregion(&sr);
197 	if (sr.length < n + 2)
198 		return (ISC_R_UNEXPECTEDEND);
199 	isc_buffer_forward(source, n + 2);
200 	return (isc_mem_tobuffer(target, sr.base, n + 2));
201 }
202 
203 static inline isc_result_t
towire_any_tsig(ARGS_TOWIRE)204 towire_any_tsig(ARGS_TOWIRE) {
205 	isc_region_t sr;
206 	dns_name_t name;
207 	dns_offsets_t offsets;
208 
209 	REQUIRE(rdata->type == dns_rdatatype_tsig);
210 	REQUIRE(rdata->rdclass == dns_rdataclass_any);
211 	REQUIRE(rdata->length != 0);
212 
213 	dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
214 	dns_rdata_toregion(rdata, &sr);
215 	dns_name_init(&name, offsets);
216 	dns_name_fromregion(&name, &sr);
217 	RETERR(dns_name_towire(&name, cctx, target));
218 	isc_region_consume(&sr, name_length(&name));
219 	return (isc_mem_tobuffer(target, sr.base, sr.length));
220 }
221 
222 static inline isc_result_t
fromstruct_any_tsig(ARGS_FROMSTRUCT)223 fromstruct_any_tsig(ARGS_FROMSTRUCT) {
224 	dns_rdata_any_tsig_t *tsig = source;
225 	isc_region_t tr;
226 
227 	REQUIRE(type == dns_rdatatype_tsig);
228 	REQUIRE(rdclass == dns_rdataclass_any);
229 	REQUIRE(source != NULL);
230 	REQUIRE(tsig->common.rdclass == rdclass);
231 	REQUIRE(tsig->common.rdtype == type);
232 
233 	UNUSED(type);
234 	UNUSED(rdclass);
235 
236 	/*
237 	 * Algorithm Name.
238 	 */
239 	RETERR(name_tobuffer(&tsig->algorithm, target));
240 
241 	isc_buffer_availableregion(target, &tr);
242 	if (tr.length < 6 + 2 + 2)
243 		return (ISC_R_NOSPACE);
244 
245 	/*
246 	 * Time Signed: 48 bits.
247 	 */
248 	RETERR(uint16_tobuffer((uint16_t)(tsig->timesigned >> 32),
249 			       target));
250 	RETERR(uint32_tobuffer((uint32_t)(tsig->timesigned & 0xffffffffU),
251 			       target));
252 
253 	/*
254 	 * Fudge.
255 	 */
256 	RETERR(uint16_tobuffer(tsig->fudge, target));
257 
258 	/*
259 	 * Signature Size.
260 	 */
261 	RETERR(uint16_tobuffer(tsig->siglen, target));
262 
263 	/*
264 	 * Signature.
265 	 */
266 	RETERR(isc_mem_tobuffer(target, tsig->signature, tsig->siglen));
267 
268 	isc_buffer_availableregion(target, &tr);
269 	if (tr.length < 2 + 2 + 2)
270 		return (ISC_R_NOSPACE);
271 
272 	/*
273 	 * Original ID.
274 	 */
275 	RETERR(uint16_tobuffer(tsig->originalid, target));
276 
277 	/*
278 	 * Error.
279 	 */
280 	RETERR(uint16_tobuffer(tsig->error, target));
281 
282 	/*
283 	 * Other Len.
284 	 */
285 	RETERR(uint16_tobuffer(tsig->otherlen, target));
286 
287 	/*
288 	 * Other Data.
289 	 */
290 	return (isc_mem_tobuffer(target, tsig->other, tsig->otherlen));
291 }
292 
293 static inline isc_result_t
tostruct_any_tsig(ARGS_TOSTRUCT)294 tostruct_any_tsig(ARGS_TOSTRUCT) {
295 	dns_rdata_any_tsig_t *tsig;
296 	dns_name_t alg;
297 	isc_region_t sr;
298 
299 	REQUIRE(rdata->type == dns_rdatatype_tsig);
300 	REQUIRE(rdata->rdclass == dns_rdataclass_any);
301 	REQUIRE(rdata->length != 0);
302 
303 	tsig = (dns_rdata_any_tsig_t *) target;
304 	tsig->common.rdclass = rdata->rdclass;
305 	tsig->common.rdtype = rdata->type;
306 	ISC_LINK_INIT(&tsig->common, link);
307 
308 	dns_rdata_toregion(rdata, &sr);
309 
310 	/*
311 	 * Algorithm Name.
312 	 */
313 	dns_name_init(&alg, NULL);
314 	dns_name_fromregion(&alg, &sr);
315 	dns_name_init(&tsig->algorithm, NULL);
316 	RETERR(name_duporclone(&alg, &tsig->algorithm));
317 
318 	isc_region_consume(&sr, name_length(&tsig->algorithm));
319 
320 	/*
321 	 * Time Signed.
322 	 */
323 	INSIST(sr.length >= 6);
324 	tsig->timesigned = ((uint64_t)sr.base[0] << 40) |
325 			   ((uint64_t)sr.base[1] << 32) |
326 			   ((uint64_t)sr.base[2] << 24) |
327 			   ((uint64_t)sr.base[3] << 16) |
328 			   ((uint64_t)sr.base[4] << 8) |
329 			   (uint64_t)sr.base[5];
330 	isc_region_consume(&sr, 6);
331 
332 	/*
333 	 * Fudge.
334 	 */
335 	tsig->fudge = uint16_fromregion(&sr);
336 	isc_region_consume(&sr, 2);
337 
338 	/*
339 	 * Signature Size.
340 	 */
341 	tsig->siglen = uint16_fromregion(&sr);
342 	isc_region_consume(&sr, 2);
343 
344 	/*
345 	 * Signature.
346 	 */
347 	INSIST(sr.length >= tsig->siglen);
348 	tsig->signature = mem_maybedup(sr.base, tsig->siglen);
349 	if (tsig->signature == NULL)
350 		goto cleanup;
351 	isc_region_consume(&sr, tsig->siglen);
352 
353 	/*
354 	 * Original ID.
355 	 */
356 	tsig->originalid = uint16_fromregion(&sr);
357 	isc_region_consume(&sr, 2);
358 
359 	/*
360 	 * Error.
361 	 */
362 	tsig->error = uint16_fromregion(&sr);
363 	isc_region_consume(&sr, 2);
364 
365 	/*
366 	 * Other Size.
367 	 */
368 	tsig->otherlen = uint16_fromregion(&sr);
369 	isc_region_consume(&sr, 2);
370 
371 	/*
372 	 * Other.
373 	 */
374 	INSIST(sr.length == tsig->otherlen);
375 	tsig->other = mem_maybedup(sr.base, tsig->otherlen);
376 	if (tsig->other == NULL)
377 		goto cleanup;
378 
379 	return (ISC_R_SUCCESS);
380 
381  cleanup:
382 	dns_name_free(&tsig->algorithm);
383 	free(tsig->signature);
384 	return (ISC_R_NOMEMORY);
385 }
386 
387 static inline void
freestruct_any_tsig(ARGS_FREESTRUCT)388 freestruct_any_tsig(ARGS_FREESTRUCT) {
389 	dns_rdata_any_tsig_t *tsig = (dns_rdata_any_tsig_t *) source;
390 
391 	REQUIRE(source != NULL);
392 	REQUIRE(tsig->common.rdtype == dns_rdatatype_tsig);
393 	REQUIRE(tsig->common.rdclass == dns_rdataclass_any);
394 
395 	dns_name_free(&tsig->algorithm);
396 	free(tsig->signature);
397 	free(tsig->other);
398 }
399 
400 #endif	/* RDATA_ANY_255_TSIG_250_C */
401