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