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