1 /*
2  * Copyright (C) 2005, 2007, 2009, 2011, 2012, 2014, 2015  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$ */
18 
19 #ifndef RDATA_GENERIC_IPSECKEY_45_C
20 #define RDATA_GENERIC_IPSECKEY_45_C
21 
22 #include <string.h>
23 
24 #include <isc/net.h>
25 
26 #define RRTYPE_IPSECKEY_ATTRIBUTES (0)
27 
28 static inline isc_result_t
fromtext_ipseckey(ARGS_FROMTEXT)29 fromtext_ipseckey(ARGS_FROMTEXT) {
30 	isc_token_t token;
31 	dns_name_t name;
32 	isc_buffer_t buffer;
33 	unsigned int gateway;
34 	struct in_addr addr;
35 	unsigned char addr6[16];
36 	isc_region_t region;
37 
38 	REQUIRE(type == dns_rdatatype_ipseckey);
39 
40 	UNUSED(type);
41 	UNUSED(rdclass);
42 	UNUSED(callbacks);
43 
44 	/*
45 	 * Precedence.
46 	 */
47 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
48 				      ISC_FALSE));
49 	if (token.value.as_ulong > 0xffU)
50 		RETTOK(ISC_R_RANGE);
51 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
52 
53 	/*
54 	 * Gateway type.
55 	 */
56 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
57 				      ISC_FALSE));
58 	if (token.value.as_ulong > 0x3U)
59 		RETTOK(ISC_R_RANGE);
60 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
61 	gateway = token.value.as_ulong;
62 
63 	/*
64 	 * Algorithm.
65 	 */
66 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
67 				      ISC_FALSE));
68 	if (token.value.as_ulong > 0xffU)
69 		RETTOK(ISC_R_RANGE);
70 	RETERR(uint8_tobuffer(token.value.as_ulong, target));
71 
72 	/*
73 	 * Gateway.
74 	 */
75 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
76 				      ISC_FALSE));
77 
78 	switch (gateway) {
79 	case 0:
80 		if (strcmp(DNS_AS_STR(token), ".") != 0)
81 			RETTOK(DNS_R_SYNTAX);
82 		break;
83 
84 	case 1:
85 		if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1)
86 			RETTOK(DNS_R_BADDOTTEDQUAD);
87 		isc_buffer_availableregion(target, &region);
88 		if (region.length < 4)
89 			return (ISC_R_NOSPACE);
90 		memmove(region.base, &addr, 4);
91 		isc_buffer_add(target, 4);
92 		break;
93 
94 	case 2:
95 		if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1)
96 			RETTOK(DNS_R_BADAAAA);
97 		isc_buffer_availableregion(target, &region);
98 		if (region.length < 16)
99 			return (ISC_R_NOSPACE);
100 		memmove(region.base, addr6, 16);
101 		isc_buffer_add(target, 16);
102 		break;
103 
104 	case 3:
105 		dns_name_init(&name, NULL);
106 		buffer_fromregion(&buffer, &token.value.as_region);
107 		if (origin == NULL)
108 			origin = dns_rootname;
109 		RETTOK(dns_name_fromtext(&name, &buffer, origin,
110 					 options, target));
111 		break;
112 	}
113 
114 	/*
115 	 * Public key.
116 	 */
117 	return (isc_base64_tobuffer(lexer, target, -1));
118 }
119 
120 static inline isc_result_t
totext_ipseckey(ARGS_TOTEXT)121 totext_ipseckey(ARGS_TOTEXT) {
122 	isc_region_t region;
123 	dns_name_t name;
124 	char buf[sizeof("255 ")];
125 	unsigned short num;
126 	unsigned short gateway;
127 
128 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
129 	REQUIRE(rdata->length >= 3);
130 
131 	dns_name_init(&name, NULL);
132 
133 	if (rdata->data[1] > 3U)
134 		return (ISC_R_NOTIMPLEMENTED);
135 
136 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
137 		RETERR(str_totext("( ", target));
138 
139 	/*
140 	 * Precedence.
141 	 */
142 	dns_rdata_toregion(rdata, &region);
143 	num = uint8_fromregion(&region);
144 	isc_region_consume(&region, 1);
145 	sprintf(buf, "%u ", num);
146 	RETERR(str_totext(buf, target));
147 
148 	/*
149 	 * Gateway type.
150 	 */
151 	gateway = uint8_fromregion(&region);
152 	isc_region_consume(&region, 1);
153 	sprintf(buf, "%u ", gateway);
154 	RETERR(str_totext(buf, target));
155 
156 	/*
157 	 * Algorithm.
158 	 */
159 	num = uint8_fromregion(&region);
160 	isc_region_consume(&region, 1);
161 	sprintf(buf, "%u ", num);
162 	RETERR(str_totext(buf, target));
163 
164 	/*
165 	 * Gateway.
166 	 */
167 	switch (gateway) {
168 	case 0:
169 		RETERR(str_totext(".", target));
170 		break;
171 
172 	case 1:
173 		RETERR(inet_totext(AF_INET, &region, target));
174 		isc_region_consume(&region, 4);
175 		break;
176 
177 	case 2:
178 		RETERR(inet_totext(AF_INET6, &region, target));
179 		isc_region_consume(&region, 16);
180 		break;
181 
182 	case 3:
183 		dns_name_fromregion(&name, &region);
184 		RETERR(dns_name_totext(&name, ISC_FALSE, target));
185 		isc_region_consume(&region, name_length(&name));
186 		break;
187 	}
188 
189 	/*
190 	 * Key.
191 	 */
192 	if (region.length > 0U) {
193 		RETERR(str_totext(tctx->linebreak, target));
194 		if (tctx->width == 0)   /* No splitting */
195 			RETERR(isc_base64_totext(&region, 60, "", target));
196 		else
197 			RETERR(isc_base64_totext(&region, tctx->width - 2,
198 						 tctx->linebreak, target));
199 	}
200 
201 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
202 		RETERR(str_totext(" )", target));
203 	return (ISC_R_SUCCESS);
204 }
205 
206 static inline isc_result_t
fromwire_ipseckey(ARGS_FROMWIRE)207 fromwire_ipseckey(ARGS_FROMWIRE) {
208 	dns_name_t name;
209 	isc_region_t region;
210 
211 	REQUIRE(type == dns_rdatatype_ipseckey);
212 
213 	UNUSED(type);
214 	UNUSED(rdclass);
215 
216 	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
217 
218 	dns_name_init(&name, NULL);
219 
220 	isc_buffer_activeregion(source, &region);
221 	if (region.length < 3)
222 		return (ISC_R_UNEXPECTEDEND);
223 
224 	switch (region.base[1]) {
225 	case 0:
226 		isc_buffer_forward(source, region.length);
227 		return (mem_tobuffer(target, region.base, region.length));
228 
229 	case 1:
230 		if (region.length < 7)
231 			return (ISC_R_UNEXPECTEDEND);
232 		isc_buffer_forward(source, region.length);
233 		return (mem_tobuffer(target, region.base, region.length));
234 
235 	case 2:
236 		if (region.length < 19)
237 			return (ISC_R_UNEXPECTEDEND);
238 		isc_buffer_forward(source, region.length);
239 		return (mem_tobuffer(target, region.base, region.length));
240 
241 	case 3:
242 		RETERR(mem_tobuffer(target, region.base, 3));
243 		isc_buffer_forward(source, 3);
244 		RETERR(dns_name_fromwire(&name, source, dctx, options, target));
245 		isc_buffer_activeregion(source, &region);
246 		isc_buffer_forward(source, region.length);
247 		return(mem_tobuffer(target, region.base, region.length));
248 
249 	default:
250 		return (ISC_R_NOTIMPLEMENTED);
251 	}
252 }
253 
254 static inline isc_result_t
towire_ipseckey(ARGS_TOWIRE)255 towire_ipseckey(ARGS_TOWIRE) {
256 	isc_region_t region;
257 
258 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
259 	REQUIRE(rdata->length != 0);
260 
261 	UNUSED(cctx);
262 
263 	dns_rdata_toregion(rdata, &region);
264 	return (mem_tobuffer(target, region.base, region.length));
265 }
266 
267 static inline int
compare_ipseckey(ARGS_COMPARE)268 compare_ipseckey(ARGS_COMPARE) {
269 	isc_region_t region1;
270 	isc_region_t region2;
271 
272 	REQUIRE(rdata1->type == rdata2->type);
273 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
274 	REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
275 	REQUIRE(rdata1->length >= 3);
276 	REQUIRE(rdata2->length >= 3);
277 
278 	dns_rdata_toregion(rdata1, &region1);
279 	dns_rdata_toregion(rdata2, &region2);
280 
281 	return (isc_region_compare(&region1, &region2));
282 }
283 
284 static inline isc_result_t
fromstruct_ipseckey(ARGS_FROMSTRUCT)285 fromstruct_ipseckey(ARGS_FROMSTRUCT) {
286 	dns_rdata_ipseckey_t *ipseckey = source;
287 	isc_region_t region;
288 	isc_uint32_t n;
289 
290 	REQUIRE(type == dns_rdatatype_ipseckey);
291 	REQUIRE(source != NULL);
292 	REQUIRE(ipseckey->common.rdtype == type);
293 	REQUIRE(ipseckey->common.rdclass == rdclass);
294 
295 	UNUSED(type);
296 	UNUSED(rdclass);
297 
298 	if (ipseckey->gateway_type > 3U)
299 		return (ISC_R_NOTIMPLEMENTED);
300 
301 	RETERR(uint8_tobuffer(ipseckey->precedence, target));
302 	RETERR(uint8_tobuffer(ipseckey->gateway_type, target));
303 	RETERR(uint8_tobuffer(ipseckey->algorithm, target));
304 
305 	switch  (ipseckey->gateway_type) {
306 	case 0:
307 		break;
308 
309 	case 1:
310 		n = ntohl(ipseckey->in_addr.s_addr);
311 		RETERR(uint32_tobuffer(n, target));
312 		break;
313 
314 	case 2:
315 		RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16));
316 		break;
317 
318 	case 3:
319 		dns_name_toregion(&ipseckey->gateway, &region);
320 		RETERR(isc_buffer_copyregion(target, &region));
321 		break;
322 	}
323 
324 	return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength));
325 }
326 
327 static inline isc_result_t
tostruct_ipseckey(ARGS_TOSTRUCT)328 tostruct_ipseckey(ARGS_TOSTRUCT) {
329 	isc_region_t region;
330 	dns_rdata_ipseckey_t *ipseckey = target;
331 	dns_name_t name;
332 	isc_uint32_t n;
333 
334 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
335 	REQUIRE(target != NULL);
336 	REQUIRE(rdata->length >= 3);
337 
338 	if (rdata->data[1] > 3U)
339 		return (ISC_R_NOTIMPLEMENTED);
340 
341 	ipseckey->common.rdclass = rdata->rdclass;
342 	ipseckey->common.rdtype = rdata->type;
343 	ISC_LINK_INIT(&ipseckey->common, link);
344 
345 	dns_name_init(&name, NULL);
346 	dns_rdata_toregion(rdata, &region);
347 
348 	ipseckey->precedence = uint8_fromregion(&region);
349 	isc_region_consume(&region, 1);
350 
351 	ipseckey->gateway_type = uint8_fromregion(&region);
352 	isc_region_consume(&region, 1);
353 
354 	ipseckey->algorithm = uint8_fromregion(&region);
355 	isc_region_consume(&region, 1);
356 
357 	switch (ipseckey->gateway_type) {
358 	case 0:
359 		break;
360 
361 	case 1:
362 		n = uint32_fromregion(&region);
363 		ipseckey->in_addr.s_addr = htonl(n);
364 		isc_region_consume(&region, 4);
365 		break;
366 
367 	case 2:
368 		memmove(ipseckey->in6_addr.s6_addr, region.base, 16);
369 		isc_region_consume(&region, 16);
370 		break;
371 
372 	case 3:
373 		dns_name_init(&ipseckey->gateway, NULL);
374 		dns_name_fromregion(&name, &region);
375 		RETERR(name_duporclone(&name, mctx, &ipseckey->gateway));
376 		isc_region_consume(&region, name_length(&name));
377 		break;
378 	}
379 
380 	ipseckey->keylength = region.length;
381 	if (ipseckey->keylength != 0U) {
382 		ipseckey->key = mem_maybedup(mctx, region.base,
383 					     ipseckey->keylength);
384 		if (ipseckey->key == NULL) {
385 			if (ipseckey->gateway_type == 3)
386 				dns_name_free(&ipseckey->gateway,
387 					      ipseckey->mctx);
388 			return (ISC_R_NOMEMORY);
389 		}
390 	} else
391 		ipseckey->key = NULL;
392 
393 	ipseckey->mctx = mctx;
394 	return (ISC_R_SUCCESS);
395 }
396 
397 static inline void
freestruct_ipseckey(ARGS_FREESTRUCT)398 freestruct_ipseckey(ARGS_FREESTRUCT) {
399 	dns_rdata_ipseckey_t *ipseckey = source;
400 
401 	REQUIRE(source != NULL);
402 	REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey);
403 
404 	if (ipseckey->mctx == NULL)
405 		return;
406 
407 	if (ipseckey->gateway_type == 3)
408 		dns_name_free(&ipseckey->gateway, ipseckey->mctx);
409 
410 	if (ipseckey->key != NULL)
411 		isc_mem_free(ipseckey->mctx, ipseckey->key);
412 
413 	ipseckey->mctx = NULL;
414 }
415 
416 static inline isc_result_t
additionaldata_ipseckey(ARGS_ADDLDATA)417 additionaldata_ipseckey(ARGS_ADDLDATA) {
418 
419 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
420 
421 	UNUSED(rdata);
422 	UNUSED(add);
423 	UNUSED(arg);
424 
425 	return (ISC_R_SUCCESS);
426 }
427 
428 static inline isc_result_t
digest_ipseckey(ARGS_DIGEST)429 digest_ipseckey(ARGS_DIGEST) {
430 	isc_region_t region;
431 
432 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
433 
434 	dns_rdata_toregion(rdata, &region);
435 	return ((digest)(arg, &region));
436 }
437 
438 static inline isc_boolean_t
checkowner_ipseckey(ARGS_CHECKOWNER)439 checkowner_ipseckey(ARGS_CHECKOWNER) {
440 
441 	REQUIRE(type == dns_rdatatype_ipseckey);
442 
443 	UNUSED(name);
444 	UNUSED(type);
445 	UNUSED(rdclass);
446 	UNUSED(wildcard);
447 
448 	return (ISC_TRUE);
449 }
450 
451 static inline isc_boolean_t
checknames_ipseckey(ARGS_CHECKNAMES)452 checknames_ipseckey(ARGS_CHECKNAMES) {
453 
454 	REQUIRE(rdata->type == dns_rdatatype_ipseckey);
455 
456 	UNUSED(rdata);
457 	UNUSED(owner);
458 	UNUSED(bad);
459 
460 	return (ISC_TRUE);
461 }
462 
463 static inline int
casecompare_ipseckey(ARGS_COMPARE)464 casecompare_ipseckey(ARGS_COMPARE) {
465 	isc_region_t region1;
466 	isc_region_t region2;
467 	dns_name_t name1;
468 	dns_name_t name2;
469 	int order;
470 
471 	REQUIRE(rdata1->type == rdata2->type);
472 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
473 	REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
474 	REQUIRE(rdata1->length >= 3);
475 	REQUIRE(rdata2->length >= 3);
476 
477 	dns_rdata_toregion(rdata1, &region1);
478 	dns_rdata_toregion(rdata2, &region2);
479 
480 	if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3)
481 		return (isc_region_compare(&region1, &region2));
482 
483 	dns_name_init(&name1, NULL);
484 	dns_name_init(&name2, NULL);
485 
486 	isc_region_consume(&region1, 3);
487 	isc_region_consume(&region2, 3);
488 
489 	dns_name_fromregion(&name1, &region1);
490 	dns_name_fromregion(&name2, &region2);
491 
492 	order = dns_name_rdatacompare(&name1, &name2);
493 	if (order != 0)
494 		return (order);
495 
496 	isc_region_consume(&region1, name_length(&name1));
497 	isc_region_consume(&region2, name_length(&name2));
498 
499 	return (isc_region_compare(&region1, &region2));
500 }
501 
502 #endif	/* RDATA_GENERIC_IPSECKEY_45_C */
503